diff options
author | Tom Yu <tlyu@mit.edu> | 2004-06-16 01:48:46 +0000 |
---|---|---|
committer | Tom Yu <tlyu@mit.edu> | 2004-06-16 01:48:46 +0000 |
commit | d7e356e114e98010f63470bc7e381dd381aa2329 (patch) | |
tree | 01aefaee6a8c7e06a700b9b9a7fe1868929e7391 | |
parent | 120df4763b45987d66873d230c09178b7f7c53f3 (diff) | |
download | krb5-d7e356e114e98010f63470bc7e381dd381aa2329.zip krb5-d7e356e114e98010f63470bc7e381dd381aa2329.tar.gz krb5-d7e356e114e98010f63470bc7e381dd381aa2329.tar.bz2 |
* kadm_rpc_svc.c (check_rpcsec_auth, gss_to_krb5_name): New
functions to check service name for RPCSEC_GSS.
(kadm_1): Add service name check for RPCSEC_GSS.
* ovsec_kadmd.c (main): Setup logging calllbacks for RPCSEC_GSS.
Use GSS_C_N_NAME for acceptor name for RPCSEC_GSS.
(log_badverf): Handle null client and server names.
* server_stubs.c (rqst2name): New function to return appropriate
gss_name_t for a given auth flavor (RPCSEC_GSS and AUTH_GSSAPI use
different field names).
ticket: 2578
status: open
git-svn-id: svn://anonsvn.mit.edu/krb5/branches/tlyu-umich-rpc@16458 dc483132-0cff-0310-8789-dd5450dbe970
-rw-r--r-- | src/kadmin/server/ChangeLog | 14 | ||||
-rw-r--r-- | src/kadmin/server/kadm_rpc_svc.c | 110 | ||||
-rw-r--r-- | src/kadmin/server/ovsec_kadmd.c | 32 | ||||
-rw-r--r-- | src/kadmin/server/server_stubs.c | 75 |
4 files changed, 177 insertions, 54 deletions
diff --git a/src/kadmin/server/ChangeLog b/src/kadmin/server/ChangeLog index c5cfd8b..9b70eec 100644 --- a/src/kadmin/server/ChangeLog +++ b/src/kadmin/server/ChangeLog @@ -1,3 +1,17 @@ +2004-06-15 Tom Yu <tlyu@mit.edu> + + * kadm_rpc_svc.c (check_rpcsec_auth, gss_to_krb5_name): New + functions to check service name for RPCSEC_GSS. + (kadm_1): Add service name check for RPCSEC_GSS. + + * ovsec_kadmd.c (main): Setup logging calllbacks for RPCSEC_GSS. + Use GSS_C_N_NAME for acceptor name for RPCSEC_GSS. + (log_badverf): Handle null client and server names. + + * server_stubs.c (rqst2name): New function to return appropriate + gss_name_t for a given auth flavor (RPCSEC_GSS and AUTH_GSSAPI use + different field names). + 2004-05-27 Tom Yu <tlyu@mit.edu> * kadm_rpc_svc.c (kadm_1): Allow RPCSEC_GSS; remove diff --git a/src/kadmin/server/kadm_rpc_svc.c b/src/kadmin/server/kadm_rpc_svc.c index a18ca1c..d2139a6 100644 --- a/src/kadmin/server/kadm_rpc_svc.c +++ b/src/kadmin/server/kadm_rpc_svc.c @@ -5,6 +5,7 @@ #include <stdio.h> #include <gssrpc/rpc.h> +#include <gssapi/gssapi_krb5.h> /* for gss_nt_krb5_name */ #include <syslog.h> #ifdef HAVE_MEMORY_H #include <memory.h> @@ -17,7 +18,15 @@ #include <arpa/inet.h> #endif #include "misc.h" +#include "kadm5/server_internal.h" +extern void *global_server_handle; + +static int check_rpcsec_auth(struct svc_req *); +static int gss_to_krb5_name(struct svc_req *, krb5_context, gss_name_t, krb5_principal *, gss_buffer_t); + +void log_badauth(OM_uint32 major, OM_uint32 minor, + struct sockaddr_in *addr, char *data); /* * Function: kadm_1 * @@ -63,8 +72,8 @@ void kadm_1(rqstp, transp) char *(*local)(); if (rqstp->rq_cred.oa_flavor != AUTH_GSSAPI && - rqstp->rq_cred.oa_flavor != RPCSEC_GSS) { - krb5_klog_syslog(LOG_ERR, "Authentication attempt failed: %s, invalid " + !check_rpcsec_auth(rqstp)) { + krb5_klog_syslog(LOG_ERR, "Authentication attempt failed: %s, " "RPC authentication flavor %d", inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr), rqstp->rq_cred.oa_flavor); @@ -227,3 +236,100 @@ void kadm_1(rqstp, transp) } return; } + +static int +check_rpcsec_auth(struct svc_req *rqstp) +{ + gss_ctx_id_t ctx; + krb5_context kctx; + OM_uint32 maj_stat, min_stat; + gss_name_t name; + krb5_principal princ; + int ret, success; + krb5_data *c1, *c2, *realm; + gss_buffer_desc gss_str; + kadm5_server_handle_t handle; + + success = 0; + handle = (kadm5_server_handle_t)global_server_handle; + + if (rqstp->rq_cred.oa_flavor != RPCSEC_GSS) + return 0; + + ctx = rqstp->rq_svccred; + + maj_stat = gss_inquire_context(&min_stat, ctx, NULL, &name, + NULL, NULL, NULL, NULL, NULL); + if (maj_stat != GSS_S_COMPLETE) { + krb5_klog_syslog(LOG_ERR, "check_rpcsec_auth: " + "failed inquire_context, stat=%u", maj_stat); + log_badauth(maj_stat, min_stat, + &rqstp->rq_xprt->xp_raddr, NULL); + goto fail_name; + } + + kctx = handle->context; + ret = gss_to_krb5_name(rqstp, kctx, name, &princ, &gss_str); + if (ret == 0) + goto fail_name; + + /* + * Since we accept with GSS_C_NO_NAME, the client can authenticate + * against the entire kdb. Therefore, ensure that the service + * name is something reasonable. + */ + if (krb5_princ_size(kctx, princ) != 2) + goto fail_princ; + + c1 = krb5_princ_component(kctx, princ, 0); + c2 = krb5_princ_component(kctx, princ, 1); + realm = krb5_princ_realm(kctx, princ); + if (strncmp(handle->params.realm, realm->data, realm->length) == 0 + && strncmp("kadmin", c1->data, c1->length) == 0) { + + if (strncmp("history", c2->data, c2->length) == 0) + goto fail_princ; + else + success = 1; + } + +fail_princ: + if (!success) { + krb5_klog_syslog(LOG_ERR, "bad service principal %.*s", + gss_str.length, gss_str.value); + } + gss_release_buffer(&min_stat, &gss_str); + krb5_free_principal(kctx, princ); +fail_name: + gss_release_name(&min_stat, &name); + return success; +} + +static int +gss_to_krb5_name(struct svc_req *rqstp, krb5_context ctx, gss_name_t gss_name, + krb5_principal *princ, gss_buffer_t gss_str) +{ + OM_uint32 status, minor_stat; + gss_OID gss_type; + char *str; + int success; + + status = gss_display_name(&minor_stat, gss_name, gss_str, &gss_type); + if ((status != GSS_S_COMPLETE) || (gss_type != gss_nt_krb5_name)) { + krb5_klog_syslog(LOG_ERR, + "gss_to_krb5_name: " + "failed display_name status %d", status); + log_badauth(status, minor_stat, + &rqstp->rq_xprt->xp_raddr, NULL); + return 0; + } + str = malloc(gss_str->length +1); + if (str == NULL) + return 0; + *str = '\0'; + + strncat(str, gss_str->value, gss_str->length); + success = (krb5_parse_name(ctx, str, princ) == 0); + free(str); + return success; +} diff --git a/src/kadmin/server/ovsec_kadmd.c b/src/kadmin/server/ovsec_kadmd.c index d3bc940..e7e995d 100644 --- a/src/kadmin/server/ovsec_kadmd.c +++ b/src/kadmin/server/ovsec_kadmd.c @@ -41,7 +41,6 @@ #include <unistd.h> #include <netinet/in.h> #include <arpa/inet.h> /* inet_ntoa */ -#include <netdb.h> #include <gssrpc/rpc.h> #include <gssapi/gssapi.h> #include "gssapiP_krb5.h" /* for kg_get_context */ @@ -208,13 +207,12 @@ int main(int argc, char *argv[]) struct sockaddr_in addr; int s; auth_gssapi_name names[4]; - char service_name[MAXHOSTNAMELEN + 8]; - char localname[MAXHOSTNAMELEN]; - struct hostent *hp; gss_buffer_desc gssbuf; gss_OID nt_krb5_name_oid; kadm5_config_params params; - + + setvbuf(stderr, NULL, _IONBF, 0); + /* This is OID value the Krb5_Name NameType */ gssbuf.value = "{1 2 840 113554 1 2 2 1}"; gssbuf.length = strlen(gssbuf.value); @@ -229,17 +227,6 @@ int main(int argc, char *argv[]) names[0].type = names[1].type = names[2].type = names[3].type = nt_krb5_name_oid; - if (gethostname(localname, MAXHOSTNAMELEN)) { - perror("gethostname"); - exit(1); - } - hp = gethostbyname(localname); - if (hp == NULL) { - perror("gethostbyname"); - exit(1); - } - sprintf(service_name, "kadmin@%s", hp->h_name); - #ifdef PURIFY purify_start_batch(); #endif /* PURIFY */ @@ -583,10 +570,11 @@ kterr: svcauth_gssapi_set_log_badverf_func(log_badverf, NULL); svcauth_gssapi_set_log_miscerr_func(log_miscerr, NULL); - in_buf.value = service_name; - in_buf.length = strlen(in_buf.value); - gss_import_name(&OMret, &in_buf, gss_nt_service_name, &gss_kadmin_name); - if (svcauth_gss_set_svc_name(gss_kadmin_name) != TRUE) { + svcauth_gss_set_log_badauth_func(log_badauth, NULL); + svcauth_gss_set_log_badverf_func(log_badverf, NULL); + svcauth_gss_set_log_miscerr_func(log_miscerr, NULL); + + if (svcauth_gss_set_svc_name(GSS_C_NO_NAME) != TRUE) { fprintf(stderr, "%s: Cannot initialize RPCSEC_GSS service name.\n", whoami); exit(1); @@ -966,6 +954,10 @@ void log_badverf(gss_name_t client_name, gss_name_t server_name, (void) gss_display_name(&minor, client_name, &client, &gss_type); (void) gss_display_name(&minor, server_name, &server, &gss_type); + if (client.value == NULL) + client.value = "(null)"; + if (server.value == NULL) + server.value = "(null)"; a = inet_ntoa(rqst->rq_xprt->xp_raddr.sin_addr); proc = msg->rm_call.cb_proc; diff --git a/src/kadmin/server/server_stubs.c b/src/kadmin/server/server_stubs.c index d087e0d..62e5daa 100644 --- a/src/kadmin/server/server_stubs.c +++ b/src/kadmin/server/server_stubs.c @@ -15,8 +15,6 @@ #include <krb5/adm_proto.h> /* krb5_klog_syslog */ #include "misc.h" -#define xdr_free gssrpc_xdr_free /* XXX kludge */ - #define LOG_UNAUTH "Unauthorized request: %s, %s, client=%s, service=%s, addr=%s" #define LOG_DONE "Request: %s, %s, %s, client=%s, service=%s, addr=%s" @@ -38,6 +36,8 @@ static int gss_name_to_string(gss_name_t gss_name, gss_buffer_desc *str); static gss_name_t acceptor_name(gss_ctx_id_t context); +static gss_name_t rqst2name(struct svc_req *rqstp); + static int cmp_gss_names(gss_name_t n1, gss_name_t n2) { OM_uint32 emaj, emin; @@ -115,8 +115,8 @@ static kadm5_ret_t new_server_handle(krb5_ui_4 api_version, *handle = *(kadm5_server_handle_t)global_server_handle; handle->api_version = api_version; - - if (! gss_to_krb5_name(handle, rqstp->rq_clntcred, + + if (! gss_to_krb5_name(handle, rqst2name(rqstp), &handle->current_caller)) { free(handle); return KADM5_FAILURE; @@ -165,7 +165,7 @@ int setup_gss_names(struct svc_req *rqstp, OM_uint32 maj_stat, min_stat; gss_name_t server_gss_name; - if (gss_name_to_string(rqstp->rq_clntcred, client_name) != 0) + if (gss_name_to_string(rqst2name(rqstp), client_name) != 0) return -1; maj_stat = gss_inquire_context(&min_stat, rqstp->rq_svccred, NULL, &server_gss_name, NULL, NULL, NULL, @@ -269,7 +269,7 @@ create_principal_1_svc(cprinc_arg *arg, struct svc_req *rqstp) } if (CHANGEPW_SERVICE(rqstp) - || !acl_check(handle->context, rqstp->rq_clntcred, ACL_ADD, + || !acl_check(handle->context, rqst2name(rqstp), ACL_ADD, arg->rec.principal, &rp) || acl_impose_restrictions(handle->context, &arg->rec, &arg->mask, rp)) { @@ -326,7 +326,7 @@ create_principal3_1_svc(cprinc3_arg *arg, struct svc_req *rqstp) } if (CHANGEPW_SERVICE(rqstp) - || !acl_check(handle->context, rqstp->rq_clntcred, ACL_ADD, + || !acl_check(handle->context, rqst2name(rqstp), ACL_ADD, arg->rec.principal, &rp) || acl_impose_restrictions(handle->context, &arg->rec, &arg->mask, rp)) { @@ -385,7 +385,7 @@ delete_principal_1_svc(dprinc_arg *arg, struct svc_req *rqstp) } if (CHANGEPW_SERVICE(rqstp) - || !acl_check(handle->context, rqstp->rq_clntcred, ACL_DELETE, + || !acl_check(handle->context, rqst2name(rqstp), ACL_DELETE, arg->princ, NULL)) { ret.code = KADM5_AUTH_DELETE; krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, "kadm5_delete_principal", @@ -436,7 +436,7 @@ modify_principal_1_svc(mprinc_arg *arg, struct svc_req *rqstp) } if (CHANGEPW_SERVICE(rqstp) - || !acl_check(handle->context, rqstp->rq_clntcred, ACL_MODIFY, + || !acl_check(handle->context, rqst2name(rqstp), ACL_MODIFY, arg->rec.principal, &rp) || acl_impose_restrictions(handle->context, &arg->rec, &arg->mask, rp)) { @@ -496,11 +496,11 @@ rename_principal_1_svc(rprinc_arg *arg, struct svc_req *rqstp) ret.code = KADM5_OK; if (! CHANGEPW_SERVICE(rqstp)) { - if (!acl_check(handle->context, rqstp->rq_clntcred, + if (!acl_check(handle->context, rqst2name(rqstp), ACL_DELETE, arg->src, NULL)) ret.code = KADM5_AUTH_DELETE; /* any restrictions at all on the ADD kills the RENAME */ - if (!acl_check(handle->context, rqstp->rq_clntcred, + if (!acl_check(handle->context, rqst2name(rqstp), ACL_ADD, arg->dest, &rp) || rp) { if (ret.code == KADM5_AUTH_DELETE) ret.code = KADM5_AUTH_INSUFFICIENT; @@ -565,9 +565,9 @@ get_principal_1_svc(gprinc_arg *arg, struct svc_req *rqstp) return &ret; } - if (! cmp_gss_krb5_name(handle, rqstp->rq_clntcred, arg->princ) && + if (! cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ) && (CHANGEPW_SERVICE(rqstp) || !acl_check(handle->context, - rqstp->rq_clntcred, + rqst2name(rqstp), ACL_INQUIRE, arg->princ, NULL))) { @@ -633,7 +633,7 @@ get_princs_1_svc(gprincs_arg *arg, struct svc_req *rqstp) prime_arg = "*"; if (CHANGEPW_SERVICE(rqstp) || !acl_check(handle->context, - rqstp->rq_clntcred, + rqst2name(rqstp), ACL_LIST, NULL, NULL)) { @@ -688,11 +688,11 @@ chpass_principal_1_svc(chpass_arg *arg, struct svc_req *rqstp) return &ret; } - if (cmp_gss_krb5_name(handle, rqstp->rq_clntcred, arg->princ)) { + if (cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ)) { ret.code = chpass_principal_wrapper_3((void *)handle, arg->princ, FALSE, 0, NULL, arg->pass); } else if (!(CHANGEPW_SERVICE(rqstp)) && - acl_check(handle->context, rqstp->rq_clntcred, + acl_check(handle->context, rqst2name(rqstp), ACL_CHANGEPW, arg->princ, NULL)) { ret.code = kadm5_chpass_principal((void *)handle, arg->princ, arg->pass); @@ -749,14 +749,14 @@ chpass_principal3_1_svc(chpass3_arg *arg, struct svc_req *rqstp) return &ret; } - if (cmp_gss_krb5_name(handle, rqstp->rq_clntcred, arg->princ)) { + if (cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ)) { ret.code = chpass_principal_wrapper_3((void *)handle, arg->princ, arg->keepold, arg->n_ks_tuple, arg->ks_tuple, arg->pass); } else if (!(CHANGEPW_SERVICE(rqstp)) && - acl_check(handle->context, rqstp->rq_clntcred, + acl_check(handle->context, rqst2name(rqstp), ACL_CHANGEPW, arg->princ, NULL)) { ret.code = kadm5_chpass_principal_3((void *)handle, arg->princ, arg->keepold, @@ -817,7 +817,7 @@ setv4key_principal_1_svc(setv4key_arg *arg, struct svc_req *rqstp) } if (!(CHANGEPW_SERVICE(rqstp)) && - acl_check(handle->context, rqstp->rq_clntcred, + acl_check(handle->context, rqst2name(rqstp), ACL_SETKEY, arg->princ, NULL)) { ret.code = kadm5_setv4key_principal((void *)handle, arg->princ, arg->keyblock); @@ -875,7 +875,7 @@ setkey_principal_1_svc(setkey_arg *arg, struct svc_req *rqstp) } if (!(CHANGEPW_SERVICE(rqstp)) && - acl_check(handle->context, rqstp->rq_clntcred, + acl_check(handle->context, rqst2name(rqstp), ACL_SETKEY, arg->princ, NULL)) { ret.code = kadm5_setkey_principal((void *)handle, arg->princ, arg->keyblocks, arg->n_keys); @@ -933,7 +933,7 @@ setkey_principal3_1_svc(setkey3_arg *arg, struct svc_req *rqstp) } if (!(CHANGEPW_SERVICE(rqstp)) && - acl_check(handle->context, rqstp->rq_clntcred, + acl_check(handle->context, rqst2name(rqstp), ACL_SETKEY, arg->princ, NULL)) { ret.code = kadm5_setkey_principal_3((void *)handle, arg->princ, arg->keepold, @@ -999,11 +999,11 @@ chrand_principal_1_svc(chrand_arg *arg, struct svc_req *rqstp) return &ret; } - if (cmp_gss_krb5_name(handle, rqstp->rq_clntcred, arg->princ)) { + if (cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ)) { ret.code = randkey_principal_wrapper_3((void *)handle, arg->princ, FALSE, 0, NULL, &k, &nkeys); } else if (!(CHANGEPW_SERVICE(rqstp)) && - acl_check(handle->context, rqstp->rq_clntcred, + acl_check(handle->context, rqst2name(rqstp), ACL_CHANGEPW, arg->princ, NULL)) { ret.code = kadm5_randkey_principal((void *)handle, arg->princ, &k, &nkeys); @@ -1075,14 +1075,14 @@ chrand_principal3_1_svc(chrand3_arg *arg, struct svc_req *rqstp) return &ret; } - if (cmp_gss_krb5_name(handle, rqstp->rq_clntcred, arg->princ)) { + if (cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ)) { ret.code = randkey_principal_wrapper_3((void *)handle, arg->princ, arg->keepold, arg->n_ks_tuple, arg->ks_tuple, &k, &nkeys); } else if (!(CHANGEPW_SERVICE(rqstp)) && - acl_check(handle->context, rqstp->rq_clntcred, + acl_check(handle->context, rqst2name(rqstp), ACL_CHANGEPW, arg->princ, NULL)) { ret.code = kadm5_randkey_principal_3((void *)handle, arg->princ, arg->keepold, @@ -1149,7 +1149,7 @@ create_policy_1_svc(cpol_arg *arg, struct svc_req *rqstp) prime_arg = arg->rec.policy; if (CHANGEPW_SERVICE(rqstp) || !acl_check(handle->context, - rqstp->rq_clntcred, + rqst2name(rqstp), ACL_ADD, NULL, NULL)) { ret.code = KADM5_AUTH_ADD; krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, "kadm5_create_policy", @@ -1200,7 +1200,7 @@ delete_policy_1_svc(dpol_arg *arg, struct svc_req *rqstp) prime_arg = arg->name; if (CHANGEPW_SERVICE(rqstp) || !acl_check(handle->context, - rqstp->rq_clntcred, + rqst2name(rqstp), ACL_DELETE, NULL, NULL)) { krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, "kadm5_delete_policy", prime_arg, client_name.value, service_name.value, @@ -1249,7 +1249,7 @@ modify_policy_1_svc(mpol_arg *arg, struct svc_req *rqstp) prime_arg = arg->rec.policy; if (CHANGEPW_SERVICE(rqstp) || !acl_check(handle->context, - rqstp->rq_clntcred, + rqst2name(rqstp), ACL_MODIFY, NULL, NULL)) { krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, "kadm5_modify_policy", prime_arg, client_name.value, service_name.value, @@ -1306,7 +1306,7 @@ get_policy_1_svc(gpol_arg *arg, struct svc_req *rqstp) ret.code = KADM5_AUTH_GET; if (!CHANGEPW_SERVICE(rqstp) && acl_check(handle->context, - rqstp->rq_clntcred, + rqst2name(rqstp), ACL_INQUIRE, NULL, NULL)) ret.code = KADM5_OK; else { @@ -1385,7 +1385,7 @@ get_pols_1_svc(gpols_arg *arg, struct svc_req *rqstp) prime_arg = "*"; if (CHANGEPW_SERVICE(rqstp) || !acl_check(handle->context, - rqstp->rq_clntcred, + rqst2name(rqstp), ACL_LIST, NULL, NULL)) { ret.code = KADM5_AUTH_LIST; krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, "kadm5_get_policies", @@ -1466,15 +1466,26 @@ generic_ret *init_1_svc(krb5_ui_4 *arg, struct svc_req *rqstp) return &ret; } - krb5_klog_syslog(LOG_NOTICE, LOG_DONE, + krb5_klog_syslog(LOG_NOTICE, LOG_DONE ", flavor=%d", (ret.api_version == KADM5_API_VERSION_1 ? "kadm5_init (V1)" : "kadm5_init"), client_name.value, (ret.code == 0) ? "success" : error_message(ret.code), client_name.value, service_name.value, - inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr)); + inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr), + rqstp->rq_cred.oa_flavor); gss_release_buffer(&minor_stat, &client_name); gss_release_buffer(&minor_stat, &service_name); return(&ret); } + +static gss_name_t +rqst2name(struct svc_req *rqstp) +{ + + if (rqstp->rq_cred.oa_flavor == RPCSEC_GSS) + return rqstp->rq_clntname; + else + return rqstp->rq_clntcred; +} |