/* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" /* * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * * Openvision retains the copyright to derivative works of * this source code. Do *NOT* create a derivative of this * source code before consulting with your legal department. * Do *NOT* integrate *ANY* of this source code into another * product before consulting with your legal department. * * For further information, read the top-level Openvision * copyright which is contained in the top-level MIT Kerberos * copyright. * * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * */ /* * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved * */ #include #include /* for gss_nt_krb5_name */ #include #include #include #include #include #include #include #include /* inet_ntoa */ #include /* krb5_klog_syslog */ #include #include "misc.h" #define LOG_UNAUTH gettext("Unauthorized request: %s, %s, " \ "client=%s, service=%s, addr=%s") #define LOG_DONE gettext("Request: %s, %s, %s, client=%s, " \ "service=%s, addr=%s") extern gss_name_t gss_changepw_name; extern gss_name_t gss_oldchangepw_name; extern void * global_server_handle; extern short l_port; char buf[33]; #define CHANGEPW_SERVICE(rqstp) \ (cmp_gss_names_rel_1(acceptor_name(rqstp), gss_changepw_name) |\ (gss_oldchangepw_name && \ cmp_gss_names_rel_1(acceptor_name(rqstp), \ gss_oldchangepw_name))) static int gss_to_krb5_name(kadm5_server_handle_t handle, gss_name_t gss_name, krb5_principal *princ); static int gss_name_to_string(gss_name_t gss_name, gss_buffer_desc *str); static gss_name_t acceptor_name(struct svc_req * rqstp); kadm5_ret_t kadm5_get_priv(void *server_handle, long *privs, gss_name_t clnt); gss_name_t get_clnt_name(struct svc_req * rqstp) { OM_uint32 maj_stat, min_stat; gss_name_t name; rpc_gss_rawcred_t *raw_cred; void *cookie; gss_buffer_desc name_buff; rpc_gss_getcred(rqstp, &raw_cred, NULL, &cookie); name_buff.value = raw_cred->client_principal->name; name_buff.length = raw_cred->client_principal->len; maj_stat = gss_import_name(&min_stat, &name_buff, (gss_OID) GSS_C_NT_EXPORT_NAME, &name); if (maj_stat != GSS_S_COMPLETE) { return (NULL); } return (name); } char * client_addr(struct svc_req * req, char *buf) { struct sockaddr *ca; u_char *b; char *frontspace = " "; /* * Convert the caller's IP address to a dotted string */ ca = (struct sockaddr *) svc_getrpccaller(req->rq_xprt)->buf; if (ca->sa_family == AF_INET) { b = (u_char *) & ((struct sockaddr_in *) ca)->sin_addr; (void) sprintf(buf, "%s(%d.%d.%d.%d) ", frontspace, b[0] & 0xFF, b[1] & 0xFF, b[2] & 0xFF, b[3] & 0xFF); } else { /* * No IP address to print. If there was a host name * printed, then we print a space. */ (void) sprintf(buf, frontspace); } return (buf); } static int cmp_gss_names(gss_name_t n1, gss_name_t n2) { OM_uint32 emaj, emin; int equal; if (GSS_ERROR(emaj = gss_compare_name(&emin, n1, n2, &equal))) return(0); return(equal); } /* Does a comparison of the names and then releases the first entity */ /* For use above in CHANGEPW_SERVICE */ static int cmp_gss_names_rel_1(gss_name_t n1, gss_name_t n2) { OM_uint32 min_stat; int ret; ret = cmp_gss_names(n1, n2); if (n1) (void) gss_release_name(&min_stat, &n1); return ret; } /* * Function check_handle * * Purpose: Check a server handle and return a com_err code if it is * invalid or 0 if it is valid. * * Arguments: * * handle The server handle. */ static int check_handle(void *handle) { CHECK_HANDLE(handle); return 0; } /* * Function: new_server_handle * * Purpose: Constructs a server handle suitable for passing into the * server library API functions, by folding the client's API version * and calling principal into the server handle returned by * kadm5_init. * * Arguments: * api_version (input) The API version specified by the client * rqstp (input) The RPC request * handle (output) The returned handle * (output) An error code, or 0 if no error occurred * * Effects: * Returns a pointer to allocated storage containing the server * handle. If an error occurs, then no allocated storage is * returned, and the return value of the function will be a * non-zero com_err code. * * The allocated storage for the handle should be freed with * free_server_handle (see below) when it is no longer needed. */ static kadm5_ret_t new_server_handle(krb5_ui_4 api_version, struct svc_req *rqstp, kadm5_server_handle_t *out_handle) { kadm5_server_handle_t handle; gss_name_t name; OM_uint32 min_stat; if (! (handle = (kadm5_server_handle_t) malloc(sizeof(*handle)))) return ENOMEM; *handle = *(kadm5_server_handle_t)global_server_handle; handle->api_version = api_version; if (!(name = get_clnt_name(rqstp))) { free(handle); return KADM5_FAILURE; } if (! gss_to_krb5_name(handle, name, &handle->current_caller)) { free(handle); gss_release_name(&min_stat, &name); return KADM5_FAILURE; } gss_release_name(&min_stat, &name); *out_handle = handle; return 0; } /* * Function: free_server_handle * * Purpose: Free handle memory allocated by new_server_handle * * Arguments: * handle (input/output) The handle to free */ static void free_server_handle(kadm5_server_handle_t handle) { krb5_free_principal(handle->context, handle->current_caller); free(handle); } /* * Function: setup_gss_names * * Purpose: Create printable representations of the client and server * names. * * Arguments: * rqstp (r) the RPC request * client_name (w) pointer to client_name string * server_name (w) pointer to server_name string * * Effects: * * Unparses the client and server names into client_name and * server_name, both of which must be freed by the caller. Returns 0 * on success and -1 on failure. On failure client_name and server_name * will point to null. */ /* SUNW14resync */ int setup_gss_names(struct svc_req *rqstp, char **client_name, char **server_name) { OM_uint32 maj_stat, min_stat; rpc_gss_rawcred_t *raw_cred; gss_buffer_desc name_buf; char *tmp, *val; size_t len; gss_name_t name; *client_name = NULL; rpc_gss_getcred(rqstp, &raw_cred, NULL, NULL); /* Return a copy of the service principal from the raw_cred */ *server_name = strdup(raw_cred->svc_principal); if (*server_name == NULL) return (-1); if (!(name = get_clnt_name(rqstp))) { free(*server_name); *server_name = NULL; return (-1); } maj_stat = gss_display_name(&min_stat, name, &name_buf, NULL); if (maj_stat != GSS_S_COMPLETE) { free(*server_name); gss_release_name(&min_stat, &name); *server_name = NULL; return (-1); } gss_release_name(&min_stat, &name); /* * Allocate space to copy the client principal. We allocate an * extra byte to make the string null terminated if we need to. */ val = name_buf.value; len = name_buf.length + (val[name_buf.length - 1] != '\0'); /* len is the length including the null terminating byte. */ tmp = malloc(len); if (tmp) { memcpy(tmp, val, len - 1); tmp[len - 1] = '\0'; } else { free(*server_name); *server_name = NULL; } /* Were done with the GSS buffer */ (void) gss_release_buffer(&min_stat, &name_buf); *client_name = tmp; return (tmp ? 0 : -1); } static gss_name_t acceptor_name(struct svc_req * rqstp) { OM_uint32 maj_stat, min_stat; gss_name_t name; rpc_gss_rawcred_t *raw_cred; void *cookie; gss_buffer_desc name_buff; rpc_gss_getcred(rqstp, &raw_cred, NULL, &cookie); name_buff.value = raw_cred->svc_principal; name_buff.length = strlen(raw_cred->svc_principal); maj_stat = gss_import_name(&min_stat, &name_buff, (gss_OID) gss_nt_krb5_name, &name); if (maj_stat != GSS_S_COMPLETE) { gss_release_buffer(&min_stat, &name_buff); return (NULL); } maj_stat = gss_display_name(&min_stat, name, &name_buff, NULL); if (maj_stat != GSS_S_COMPLETE) { gss_release_buffer(&min_stat, &name_buff); return (NULL); } gss_release_buffer(&min_stat, &name_buff); return name; } static int cmp_gss_krb5_name(kadm5_server_handle_t handle, gss_name_t gss_name, krb5_principal princ) { krb5_principal princ2; int status; if (! gss_to_krb5_name(handle, gss_name, &princ2)) return 0; status = krb5_principal_compare(handle->context, princ, princ2); krb5_free_principal(handle->context, princ2); return status; } /* * This routine primarily validates the username and password * of the principal to be created, if a prior acl check for * the 'u' privilege succeeds. Validation is done using * the PAM `k5migrate' service. k5migrate normally stacks * pam_unix_auth.so and pam_unix_account.so in its auth and * account stacks respectively. * * Returns 1 (true), if validation is successful, * else returns 0 (false). */ int verify_pam_pw(char *userdata, char *pwd) { pam_handle_t *pamh; int err = 0; int result = 1; char *user = NULL; char *ptr = NULL; ptr = strchr(userdata, '@'); if (ptr != NULL) { user = (char *)malloc(ptr - userdata + 1); (void) strlcpy(user, userdata, (ptr - userdata) + 1); } else { user = (char *)strdup(userdata); } err = pam_start("k5migrate", user, NULL, &pamh); if (err != PAM_SUCCESS) { syslog(LOG_ERR, "verify_pam_pw: pam_start() failed, %s\n", pam_strerror(pamh, err)); if (user) free(user); return (0); } if (user) free(user); err = pam_set_item(pamh, PAM_AUTHTOK, (void *)pwd); if (err != PAM_SUCCESS) { syslog(LOG_ERR, "verify_pam_pw: pam_set_item() failed, %s\n", pam_strerror(pamh, err)); (void) pam_end(pamh, err); return (0); } err = pam_authenticate(pamh, PAM_SILENT); if (err != PAM_SUCCESS) { syslog(LOG_ERR, "verify_pam_pw: pam_authenticate() " "failed, %s\n", pam_strerror(pamh, err)); (void) pam_end(pamh, err); return (0); } err = pam_acct_mgmt(pamh, PAM_SILENT); if (err != PAM_SUCCESS) { syslog(LOG_ERR, "verify_pam_pw: pam_acct_mgmt() failed, %s\n", pam_strerror(pamh, err)); (void) pam_end(pamh, err); return (0); } (void) pam_end(pamh, PAM_SUCCESS); return (result); } static int gss_to_krb5_name(kadm5_server_handle_t handle, gss_name_t gss_name, krb5_principal *princ) { OM_uint32 status, minor_stat; gss_buffer_desc gss_str; gss_OID gss_type; int success; status = gss_display_name(&minor_stat, gss_name, &gss_str, &gss_type); if ((status != GSS_S_COMPLETE) || (!g_OID_equal(gss_type, gss_nt_krb5_name))) return 0; success = (krb5_parse_name(handle->context, gss_str.value, princ) == 0); gss_release_buffer(&minor_stat, &gss_str); return success; } static int gss_name_to_string(gss_name_t gss_name, gss_buffer_desc *str) { OM_uint32 status, minor_stat; gss_OID gss_type; status = gss_display_name(&minor_stat, gss_name, str, &gss_type); if ((status != GSS_S_COMPLETE) || (gss_type != gss_nt_krb5_name)) return 1; return 0; } static int log_unauth( char *op, char *target, char *client, char *server, char *addr) { size_t tlen, clen, slen; char *tdots, *cdots, *sdots; tlen = strlen(target); trunc_name(&tlen, &tdots); clen = strlen(client); trunc_name(&clen, &cdots); slen = strlen(server); trunc_name(&slen, &sdots); return krb5_klog_syslog(LOG_NOTICE, "Unauthorized request: %s, %.*s%s, " "client=%.*s%s, service=%.*s%s, addr=%s", op, tlen, target, tdots, clen, client, cdots, slen, server, sdots, addr); } static int log_done( char *op, char *target, const char *errmsg, char *client, char *server, char *addr) { size_t tlen, clen, slen; char *tdots, *cdots, *sdots; tlen = strlen(target); trunc_name(&tlen, &tdots); clen = strlen(client); trunc_name(&clen, &cdots); slen = strlen(server); trunc_name(&slen, &sdots); return krb5_klog_syslog(LOG_NOTICE, "Request: %s, %.*s%s, %s, " "client=%.*s%s, service=%.*s%s, addr=%s", op, tlen, target, tdots, errmsg, clen, client, cdots, slen, server, sdots, addr); } generic_ret * create_principal_1_svc(cprinc_arg *arg, struct svc_req *rqstp) { static generic_ret ret; char *prime_arg = NULL; char *client_name = NULL, *service_name = NULL; int policy_migrate = 0; OM_uint32 minor_stat; kadm5_server_handle_t handle; kadm5_ret_t retval; restriction_t *rp; gss_name_t name = NULL; xdr_free(xdr_generic_ret, (char *) &ret); if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle))) return &ret; if ((ret.code = check_handle((void *)handle))) goto error; ret.api_version = handle->api_version; if (setup_gss_names(rqstp, &client_name, &service_name) < 0) { ret.code = KADM5_FAILURE; goto error; } if (krb5_unparse_name(handle->context, arg->rec.principal, &prime_arg)) { ret.code = KADM5_BAD_PRINCIPAL; goto error; } if (!(name = get_clnt_name(rqstp))) { ret.code = KADM5_FAILURE; goto error; } if (kadm5int_acl_check(handle->context, name, ACL_MIGRATE, arg->rec.principal, &rp) && verify_pam_pw(prime_arg, arg->passwd)) { policy_migrate = 1; } if (CHANGEPW_SERVICE(rqstp) || (!kadm5int_acl_check(handle->context, name, ACL_ADD, arg->rec.principal, &rp) && !(policy_migrate)) || kadm5int_acl_impose_restrictions(handle->context, &arg->rec, &arg->mask, rp)) { ret.code = KADM5_AUTH_ADD; audit_kadmind_unauth(rqstp->rq_xprt, l_port, "kadm5_create_principal", prime_arg, client_name); log_unauth("kadm5_create_principal", prime_arg, client_name, service_name, client_addr(rqstp, buf)); } else { ret.code = kadm5_create_principal((void *)handle, &arg->rec, arg->mask, arg->passwd); audit_kadmind_auth(rqstp->rq_xprt, l_port, "kadm5_create_principal", prime_arg, client_name, ret.code); log_done("kadm5_create_principal", prime_arg, ((ret.code == 0) ? "success" : error_message(ret.code)), client_name, service_name, client_addr(rqstp, buf)); if (policy_migrate && (ret.code == 0)) { arg->rec.policy = strdup("default"); if ((arg->mask & KADM5_PW_EXPIRATION)) { arg->mask = 0; arg->mask |= KADM5_POLICY; arg->mask |= KADM5_PW_EXPIRATION; } else { arg->mask = 0; arg->mask |= KADM5_POLICY; } retval = kadm5_modify_principal((void *)handle, &arg->rec, arg->mask); log_done("kadm5_modify_principal", prime_arg, ((retval == 0) ? "success" : error_message(retval)), client_name, service_name, client_addr(rqstp, buf)); } } error: if (name) gss_release_name(&minor_stat, &name); free_server_handle(handle); if (prime_arg) free(prime_arg); if (client_name) free(client_name); if (service_name) free(service_name); return (&ret); } generic_ret * create_principal3_1_svc(cprinc3_arg *arg, struct svc_req *rqstp) { static generic_ret ret; char *prime_arg = NULL; char *client_name = NULL, *service_name = NULL; int policy_migrate = 0; OM_uint32 minor_stat; kadm5_server_handle_t handle; kadm5_ret_t retval; restriction_t *rp; gss_name_t name = NULL; xdr_free(xdr_generic_ret, (char *) &ret); if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle))) return &ret; if ((ret.code = check_handle((void *)handle))) goto error; ret.api_version = handle->api_version; if (setup_gss_names(rqstp, &client_name, &service_name) < 0) { ret.code = KADM5_FAILURE; goto error; } if (krb5_unparse_name(handle->context, arg->rec.principal, &prime_arg)) { ret.code = KADM5_BAD_PRINCIPAL; goto error; } if (!(name = get_clnt_name(rqstp))) { ret.code = KADM5_FAILURE; goto error; } if (kadm5int_acl_check(handle->context, name, ACL_MIGRATE, arg->rec.principal, &rp) && verify_pam_pw(prime_arg, arg->passwd)) { policy_migrate = 1; } if (CHANGEPW_SERVICE(rqstp) || (!kadm5int_acl_check(handle->context, name, ACL_ADD, arg->rec.principal, &rp) && !(policy_migrate)) || kadm5int_acl_impose_restrictions(handle->context, &arg->rec, &arg->mask, rp)) { ret.code = KADM5_AUTH_ADD; log_unauth("kadm5_create_principal", prime_arg, client_name, service_name, client_addr(rqstp, buf)); } else { ret.code = kadm5_create_principal_3((void *)handle, &arg->rec, arg->mask, arg->n_ks_tuple, arg->ks_tuple, arg->passwd); log_done("kadm5_create_principal", prime_arg, ((ret.code == 0) ? "success" : error_message(ret.code)), client_name, service_name, client_addr(rqstp, buf)); if (policy_migrate && (ret.code == 0)) { arg->rec.policy = strdup("default"); if ((arg->mask & KADM5_PW_EXPIRATION)) { arg->mask = 0; arg->mask |= KADM5_POLICY; arg->mask |= KADM5_PW_EXPIRATION; } else { arg->mask = 0; arg->mask |= KADM5_POLICY; } retval = kadm5_modify_principal((void *)handle, &arg->rec, arg->mask); log_done("kadm5_modify_principal", prime_arg, ((retval == 0) ? "success" : error_message(retval)), client_name, service_name, client_addr(rqstp, buf)); } } error: if (name) gss_release_name(&minor_stat, &name); free_server_handle(handle); if (client_name) free(client_name); if (service_name) free(service_name); if (prime_arg) free(prime_arg); return &ret; } generic_ret * delete_principal_1_svc(dprinc_arg *arg, struct svc_req *rqstp) { static generic_ret ret; char *prime_arg = NULL; char *client_name = NULL, *service_name = NULL; OM_uint32 min_stat; kadm5_server_handle_t handle; gss_name_t name = NULL; xdr_free(xdr_generic_ret, (char *) &ret); if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle))) return &ret; if ((ret.code = check_handle((void *)handle))) goto error; ret.api_version = handle->api_version; if (setup_gss_names(rqstp, &client_name, &service_name) < 0) { ret.code = KADM5_FAILURE; goto error; } if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) { ret.code = KADM5_BAD_PRINCIPAL; goto error; } if (!(name = get_clnt_name(rqstp))) { ret.code = KADM5_FAILURE; goto error; } if (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context, name, ACL_DELETE, arg->princ, NULL)) { ret.code = KADM5_AUTH_DELETE; audit_kadmind_unauth(rqstp->rq_xprt, l_port, "kadm5_delete_principal", prime_arg, client_name); log_unauth("kadm5_delete_principal", prime_arg, client_name, service_name, client_addr(rqstp, buf)); } else { ret.code = kadm5_delete_principal((void *)handle, arg->princ); audit_kadmind_auth(rqstp->rq_xprt, l_port, "kadm5_delete_principal", prime_arg, client_name, ret.code); log_done("kadm5_delete_principal", prime_arg, ((ret.code == 0) ? "success" : error_message(ret.code)), client_name, service_name, client_addr(rqstp, buf)); } error: if (name) gss_release_name(&min_stat, &name); if (prime_arg) free(prime_arg); free_server_handle(handle); if (client_name) free(client_name); if (service_name) free(service_name); return &ret; } generic_ret * modify_principal_1_svc(mprinc_arg *arg, struct svc_req *rqstp) { static generic_ret ret; char *prime_arg = NULL; char *client_name = NULL, *service_name = NULL; OM_uint32 min_stat; kadm5_server_handle_t handle; restriction_t *rp; gss_name_t name = NULL; xdr_free(xdr_generic_ret, (char *) &ret); if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle))) return &ret; if ((ret.code = check_handle((void *)handle))) goto error; if (setup_gss_names(rqstp, &client_name, &service_name) < 0) { ret.code = KADM5_FAILURE; goto error; } if (krb5_unparse_name(handle->context, arg->rec.principal, &prime_arg)) { ret.code = KADM5_BAD_PRINCIPAL; goto error; } if (!(name = get_clnt_name(rqstp))) { ret.code = KADM5_FAILURE; goto error; } if (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context, name, ACL_MODIFY, arg->rec.principal, &rp) || kadm5int_acl_impose_restrictions(handle->context, &arg->rec, &arg->mask, rp)) { ret.code = KADM5_AUTH_MODIFY; audit_kadmind_unauth(rqstp->rq_xprt, l_port, "kadm5_modify_principal", prime_arg, client_name); log_unauth("kadm5_modify_principal", prime_arg, client_name, service_name, client_addr(rqstp, buf)); } else { ret.code = kadm5_modify_principal((void *)handle, &arg->rec, arg->mask); audit_kadmind_auth(rqstp->rq_xprt, l_port, "kadm5_modify_principal", prime_arg, client_name, ret.code); log_done("kadm5_modify_principal", prime_arg, ((ret.code == 0) ? "success" : error_message(ret.code)), client_name, service_name, client_addr(rqstp, buf)); } error: if (name) gss_release_name(&min_stat, &name); free_server_handle(handle); if (prime_arg) free(prime_arg); if (client_name) free(client_name); if (service_name) free(service_name); return &ret; } generic_ret * rename_principal_1_svc(rprinc_arg *arg, struct svc_req *rqstp) { static generic_ret ret; char *prime_arg1 = NULL, *prime_arg2 = NULL; char prime_arg[BUFSIZ]; char *client_name = NULL, *service_name = NULL; OM_uint32 min_stat; kadm5_server_handle_t handle; restriction_t *rp; gss_name_t name = NULL; size_t tlen1, tlen2, clen, slen; char *tdots1, *tdots2, *cdots, *sdots; xdr_free(xdr_generic_ret, (char *) &ret); if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle))) return &ret; if ((ret.code = check_handle((void *)handle))) goto error; if (setup_gss_names(rqstp, &client_name, &service_name) < 0) { ret.code = KADM5_FAILURE; goto error; } if (krb5_unparse_name(handle->context, arg->src, &prime_arg1) || krb5_unparse_name(handle->context, arg->dest, &prime_arg2)) { ret.code = KADM5_BAD_PRINCIPAL; goto error; } tlen1 = strlen(prime_arg1); trunc_name(&tlen1, &tdots1); tlen2 = strlen(prime_arg2); trunc_name(&tlen2, &tdots2); clen = strlen(client_name); trunc_name(&clen, &cdots); slen = strlen(service_name); trunc_name(&slen, &sdots); (void) snprintf(prime_arg, sizeof (prime_arg), "%.*s%s to %.*s*s", tlen1, prime_arg1, tdots1, tlen2, prime_arg2, tdots2); ret.code = KADM5_OK; if (!(name = get_clnt_name(rqstp))) { ret.code = KADM5_FAILURE; goto error; } if (! CHANGEPW_SERVICE(rqstp)) { if (!kadm5int_acl_check(handle->context, name, ACL_DELETE, arg->src, NULL)) ret.code = KADM5_AUTH_DELETE; /* any restrictions at all on the ADD kills the RENAME */ if (!kadm5int_acl_check(handle->context, name, ACL_ADD, arg->dest, &rp)) { if (ret.code == KADM5_AUTH_DELETE) ret.code = KADM5_AUTH_INSUFFICIENT; else ret.code = KADM5_AUTH_ADD; } } else ret.code = KADM5_AUTH_INSUFFICIENT; if (ret.code != KADM5_OK) { audit_kadmind_unauth(rqstp->rq_xprt, l_port, "kadm5_rename_principal", prime_arg, client_name); krb5_klog_syslog(LOG_NOTICE, "Unauthorized request: kadm5_rename_principal, " "%.*s%s to %.*s%s, " "client=%.*s%s, service=%.*s%s, addr=%s", tlen1, prime_arg1, tdots1, tlen2, prime_arg2, tdots2, clen, client_name, cdots, slen, service_name, sdots, client_addr(rqstp, buf)); } else { ret.code = kadm5_rename_principal((void *)handle, arg->src, arg->dest); audit_kadmind_auth(rqstp->rq_xprt, l_port, "kadm5_rename_principal", prime_arg, client_name, ret.code); krb5_klog_syslog(LOG_NOTICE, "Request: kadm5_rename_principal, " "%.*s%s to %.*s%s, %s, " "client=%.*s%s, service=%.*s%s, addr=%s", tlen1, prime_arg1, tdots1, tlen2, prime_arg2, tdots2, clen, client_name, cdots, slen, service_name, sdots, client_addr(rqstp, buf)); } error: if (name) gss_release_name(&min_stat, &name); free_server_handle(handle); if (prime_arg1) free(prime_arg1); if (prime_arg2) free(prime_arg2); if (client_name) free(client_name); if (service_name) free(service_name); return &ret; } gprinc_ret * get_principal_1_svc(gprinc_arg *arg, struct svc_req *rqstp) { static gprinc_ret ret; kadm5_principal_ent_t_v1 e; char *prime_arg = NULL, *funcname; char *client_name = NULL, *service_name = NULL; OM_uint32 min_stat; kadm5_server_handle_t handle; gss_name_t name = NULL; xdr_free(xdr_gprinc_ret, (char *) &ret); if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle))) return &ret; if ((ret.code = check_handle((void *)handle))) goto error; ret.api_version = handle->api_version; funcname = handle->api_version == KADM5_API_VERSION_1 ? "kadm5_get_principal (V1)" : "kadm5_get_principal"; if (setup_gss_names(rqstp, &client_name, &service_name) < 0) { ret.code = KADM5_FAILURE; goto error; } if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) { ret.code = KADM5_BAD_PRINCIPAL; goto error; } if (!(name = get_clnt_name(rqstp))) { ret.code = KADM5_FAILURE; goto error; } if (! cmp_gss_krb5_name(handle, name, arg->princ) && (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context, name, ACL_INQUIRE, arg->princ, NULL))) { ret.code = KADM5_AUTH_GET; audit_kadmind_unauth(rqstp->rq_xprt, l_port, funcname, prime_arg, client_name); log_unauth(funcname, prime_arg, client_name, service_name, client_addr(rqstp, buf)); } else { if (handle->api_version == KADM5_API_VERSION_1) { ret.code = kadm5_get_principal_v1((void *)handle, arg->princ, &e); if(ret.code == KADM5_OK) { memcpy(&ret.rec, e, sizeof(kadm5_principal_ent_rec_v1)); free(e); } } else { ret.code = kadm5_get_principal((void *)handle, arg->princ, &ret.rec, arg->mask); } audit_kadmind_auth(rqstp->rq_xprt, l_port, funcname, prime_arg, client_name, ret.code); log_done(funcname, prime_arg, ((ret.code == 0) ? "success" : error_message(ret.code)), client_name, service_name, client_addr(rqstp, buf)); } error: if (name) gss_release_name(&min_stat, &name); free_server_handle(handle); if (prime_arg) free(prime_arg); if (client_name) free(client_name); if (service_name) free(service_name); return &ret; } gprincs_ret * get_princs_1_svc(gprincs_arg *arg, struct svc_req *rqstp) { static gprincs_ret ret; char *prime_arg = NULL; char *client_name = NULL, *service_name = NULL; OM_uint32 min_stat; kadm5_server_handle_t handle; gss_name_t name = NULL; xdr_free(xdr_gprincs_ret, (char *) &ret); if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle))) return &ret; if ((ret.code = check_handle((void *)handle))) goto error; ret.api_version = handle->api_version; if (setup_gss_names(rqstp, &client_name, &service_name) < 0) { ret.code = KADM5_FAILURE; goto error; } prime_arg = arg->exp; if (prime_arg == NULL) prime_arg = "*"; if (!(name = get_clnt_name(rqstp))) { ret.code = KADM5_FAILURE; goto error; } if (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context, name, ACL_LIST, NULL, NULL)) { ret.code = KADM5_AUTH_LIST; audit_kadmind_unauth(rqstp->rq_xprt, l_port, "kadm5_get_principals", prime_arg, client_name); log_unauth("kadm5_get_principals", prime_arg, client_name, service_name, client_addr(rqstp, buf)); } else { ret.code = kadm5_get_principals((void *)handle, arg->exp, &ret.princs, &ret.count); audit_kadmind_auth(rqstp->rq_xprt, l_port, "kadm5_get_principals", prime_arg, client_name, ret.code); log_done("kadm5_get_principals", prime_arg, ((ret.code == 0) ? "success" : error_message(ret.code)), client_name, service_name, client_addr(rqstp, buf)); } error: if (name) gss_release_name(&min_stat, &name); free_server_handle(handle); if (client_name) free(client_name); if (service_name) free(service_name); return (&ret); } generic_ret * chpass_principal_1_svc(chpass_arg *arg, struct svc_req *rqstp) { static generic_ret ret; char *prime_arg = NULL; char *client_name = NULL, *service_name = NULL; OM_uint32 min_stat; kadm5_server_handle_t handle; gss_name_t name = NULL; xdr_free(xdr_generic_ret, (char *) &ret); if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle))) return &ret; if ((ret.code = check_handle((void *)handle))) goto error; ret.api_version = handle->api_version; if (setup_gss_names(rqstp, &client_name, &service_name) < 0) { ret.code = KADM5_FAILURE; goto error; } if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) { ret.code = KADM5_BAD_PRINCIPAL; goto error; } if (!(name = get_clnt_name(rqstp))) { ret.code = KADM5_FAILURE; goto error; } if (cmp_gss_krb5_name(handle, name, arg->princ)) { ret.code = chpass_principal_wrapper_3((void *)handle, arg->princ, FALSE, 0, NULL, arg->pass); } else if (!(CHANGEPW_SERVICE(rqstp)) && kadm5int_acl_check(handle->context, name, ACL_CHANGEPW, arg->princ, NULL)) { ret.code = kadm5_chpass_principal((void *)handle, arg->princ, arg->pass); } else { audit_kadmind_unauth(rqstp->rq_xprt, l_port, "kadm5_chpass_principal", prime_arg, client_name); log_unauth("kadm5_chpass_principal", prime_arg, client_name, service_name, client_addr(rqstp, buf)); ret.code = KADM5_AUTH_CHANGEPW; } if(ret.code != KADM5_AUTH_CHANGEPW) { audit_kadmind_auth(rqstp->rq_xprt, l_port, "kadm5_chpass_principal", prime_arg, client_name, ret.code); log_done("kadm5_chpass_principal", prime_arg, ((ret.code == 0) ? "success" : error_message(ret.code)), client_name, service_name, client_addr(rqstp, buf)); } error: if (name) gss_release_name(&min_stat, &name); free_server_handle(handle); if (prime_arg) free(prime_arg); if (client_name) free(client_name); if (service_name) free(service_name); return (&ret); } generic_ret * chpass_principal3_1_svc(chpass3_arg *arg, struct svc_req *rqstp) { static generic_ret ret; char *prime_arg = NULL; char *client_name = NULL, *service_name = NULL; OM_uint32 min_stat; kadm5_server_handle_t handle; gss_name_t name = NULL; xdr_free(xdr_generic_ret, (char *) &ret); if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle))) return &ret; if ((ret.code = check_handle((void *)handle))) goto error; ret.api_version = handle->api_version; if (setup_gss_names(rqstp, &client_name, &service_name) < 0) { ret.code = KADM5_FAILURE; goto error; } if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) { ret.code = KADM5_BAD_PRINCIPAL; goto error; } if (!(name = get_clnt_name(rqstp))) { ret.code = KADM5_FAILURE; goto error; } if (cmp_gss_krb5_name(handle, name, 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)) && kadm5int_acl_check(handle->context, name, ACL_CHANGEPW, arg->princ, NULL)) { ret.code = kadm5_chpass_principal_3((void *)handle, arg->princ, arg->keepold, arg->n_ks_tuple, arg->ks_tuple, arg->pass); } else { log_unauth("kadm5_chpass_principal", prime_arg, client_name, service_name, client_addr(rqstp, buf)); ret.code = KADM5_AUTH_CHANGEPW; } if(ret.code != KADM5_AUTH_CHANGEPW) { log_done("kadm5_chpass_principal", prime_arg, ((ret.code == 0) ? "success" : error_message(ret.code)), client_name, service_name, client_addr(rqstp, buf)); } error: if (name) gss_release_name(&min_stat, &name); free_server_handle(handle); if (client_name) free(client_name); if (service_name) free(service_name); if (prime_arg) free(prime_arg); return (&ret); } #ifdef SUNWOFF generic_ret * setv4key_principal_1_svc(setv4key_arg *arg, struct svc_req *rqstp) { static generic_ret ret; char *prime_arg = NULL; char *client_name = NULL, *service_name = NULL; OM_uint32 min_stat; kadm5_server_handle_t handle; gss_name_t name = NULL; xdr_free(xdr_generic_ret, (char *) &ret); if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle))) return &ret; if ((ret.code = check_handle((void *)handle))) goto error; ret.api_version = handle->api_version; if (setup_gss_names(rqstp, &client_name, &service_name) < 0) { ret.code = KADM5_FAILURE; goto error; } if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) { ret.code = KADM5_BAD_PRINCIPAL; goto error; } if (!(name = get_clnt_name(rqstp))) { ret.code = KADM5_FAILURE; goto error; } if (!(CHANGEPW_SERVICE(rqstp)) && kadm5int_acl_check(handle->context, name, ACL_SETKEY, arg->princ, NULL)) { ret.code = kadm5_setv4key_principal((void *)handle, arg->princ, arg->keyblock); } else { log_unauth("kadm5_setv4key_principal", prime_arg, client_name, service_name, client_addr(rqstp, buf)); ret.code = KADM5_AUTH_SETKEY; } if(ret.code != KADM5_AUTH_SETKEY) { log_done("kadm5_setv4key_principal", prime_arg, ((ret.code == 0) ? "success" : error_message(ret.code)), client_name, service_name, client_addr(rqstp, buf)); } error: if (name) gss_release_name(&min_stat, &name); free_server_handle(handle); if (client_name) free(client_name); if (service_name) free(service_name); if (prime_arg) free(prime_arg); return (&ret); } #endif generic_ret * setkey_principal_1_svc(setkey_arg *arg, struct svc_req *rqstp) { static generic_ret ret; char *prime_arg; char *client_name, *service_name; OM_uint32 min_stat; kadm5_server_handle_t handle; gss_name_t name; xdr_free(xdr_generic_ret, (char *) &ret); if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle))) return &ret; if ((ret.code = check_handle((void *)handle))) goto error; ret.api_version = handle->api_version; if (setup_gss_names(rqstp, &client_name, &service_name) < 0) { ret.code = KADM5_FAILURE; goto error; } if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) { ret.code = KADM5_BAD_PRINCIPAL; goto error; } if (!(name = get_clnt_name(rqstp))) { ret.code = KADM5_FAILURE; goto error; } if (!(CHANGEPW_SERVICE(rqstp)) && kadm5int_acl_check(handle->context, name, ACL_SETKEY, arg->princ, NULL)) { ret.code = kadm5_setkey_principal((void *)handle, arg->princ, arg->keyblocks, arg->n_keys); } else { log_unauth("kadm5_setkey_principal", prime_arg, client_name, service_name, client_addr(rqstp, buf)); ret.code = KADM5_AUTH_SETKEY; } if(ret.code != KADM5_AUTH_SETKEY) { log_done("kadm5_setkey_principal", prime_arg, ((ret.code == 0) ? "success" : error_message(ret.code)), client_name, service_name, client_addr(rqstp, buf)); } error: if (name) gss_release_name(&min_stat, &name); free_server_handle(handle); if (client_name) free(client_name); if (service_name) free(service_name); if (prime_arg) free(prime_arg); return (&ret); } generic_ret * setkey_principal3_1_svc(setkey3_arg *arg, struct svc_req *rqstp) { static generic_ret ret; char *prime_arg = NULL; char *client_name = NULL, *service_name = NULL; OM_uint32 min_stat; kadm5_server_handle_t handle; gss_name_t name = NULL; xdr_free(xdr_generic_ret, (char *) &ret); if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle))) return &ret; if ((ret.code = check_handle((void *)handle))) goto error; ret.api_version = handle->api_version; if (setup_gss_names(rqstp, &client_name, &service_name) < 0) { ret.code = KADM5_FAILURE; goto error; } if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) { ret.code = KADM5_BAD_PRINCIPAL; goto error; } if (!(name = get_clnt_name(rqstp))) { ret.code = KADM5_FAILURE; goto error; } if (!(CHANGEPW_SERVICE(rqstp)) && kadm5int_acl_check(handle->context, name, ACL_SETKEY, arg->princ, NULL)) { ret.code = kadm5_setkey_principal_3((void *)handle, arg->princ, arg->keepold, arg->n_ks_tuple, arg->ks_tuple, arg->keyblocks, arg->n_keys); } else { log_unauth("kadm5_setkey_principal", prime_arg, client_name, service_name, client_addr(rqstp, buf)); ret.code = KADM5_AUTH_SETKEY; } if(ret.code != KADM5_AUTH_SETKEY) { log_done("kadm5_setkey_principal", prime_arg, ((ret.code == 0) ? "success" : error_message(ret.code)), client_name, service_name, client_addr(rqstp, buf)); } error: if (name) gss_release_name(&min_stat, &name); free_server_handle(handle); if (client_name) free(client_name); if (service_name) free(service_name); if (prime_arg) free(prime_arg); return &ret; } chrand_ret * chrand_principal_1_svc(chrand_arg *arg, struct svc_req *rqstp) { static chrand_ret ret; krb5_keyblock *k; int nkeys; char *prime_arg = NULL, *funcname; char *client_name = NULL, *service_name = NULL; OM_uint32 min_stat; kadm5_server_handle_t handle; gss_name_t name = NULL; xdr_free(xdr_chrand_ret, (char *) &ret); if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle))) return &ret; if ((ret.code = check_handle((void *)handle))) goto error; ret.api_version = handle->api_version; funcname = handle->api_version == KADM5_API_VERSION_1 ? "kadm5_randkey_principal (V1)" : "kadm5_randkey_principal"; if (setup_gss_names(rqstp, &client_name, &service_name) < 0) { ret.code = KADM5_FAILURE; goto error; } if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) { ret.code = KADM5_BAD_PRINCIPAL; goto error; } if (!(name = get_clnt_name(rqstp))) { ret.code = KADM5_FAILURE; goto error; } if (cmp_gss_krb5_name(handle, name, arg->princ)) { ret.code = randkey_principal_wrapper((void *)handle, arg->princ, &k, &nkeys); } else if (!(CHANGEPW_SERVICE(rqstp)) && kadm5int_acl_check(handle->context, name, ACL_CHANGEPW, arg->princ, NULL)) { ret.code = kadm5_randkey_principal((void *)handle, arg->princ, &k, &nkeys); } else { audit_kadmind_unauth(rqstp->rq_xprt, l_port, funcname, prime_arg, client_name); log_unauth(funcname, prime_arg, client_name, service_name, client_addr(rqstp, buf)); ret.code = KADM5_AUTH_CHANGEPW; } if(ret.code == KADM5_OK) { if (handle->api_version == KADM5_API_VERSION_1) { krb5_copy_keyblock_contents(handle->context, k, &ret.key); krb5_free_keyblock(handle->context, k); } else { ret.keys = k; ret.n_keys = nkeys; } } if(ret.code != KADM5_AUTH_CHANGEPW) { audit_kadmind_auth(rqstp->rq_xprt, l_port, funcname, prime_arg, client_name, ret.code); log_done(funcname, prime_arg, ((ret.code == 0) ? "success" : error_message(ret.code)), client_name, service_name, client_addr(rqstp, buf)); } error: if (name) gss_release_name(&min_stat, &name); free_server_handle(handle); if (prime_arg) free(prime_arg); if (client_name) free(client_name); if (service_name) free(service_name); return &ret; } chrand_ret * chrand_principal3_1_svc(chrand3_arg *arg, struct svc_req *rqstp) { static chrand_ret ret; krb5_keyblock *k; int nkeys; char *prime_arg = NULL, *funcname; char *client_name = NULL, *service_name = NULL; OM_uint32 min_stat; kadm5_server_handle_t handle; gss_name_t name = NULL; xdr_free(xdr_chrand_ret, (char *) &ret); if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle))) return &ret; if ((ret.code = check_handle((void *)handle))) goto error; ret.api_version = handle->api_version; funcname = handle->api_version == KADM5_API_VERSION_1 ? "kadm5_randkey_principal (V1)" : "kadm5_randkey_principal"; if (setup_gss_names(rqstp, &client_name, &service_name) < 0) { ret.code = KADM5_FAILURE; goto error; } if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) { ret.code = KADM5_BAD_PRINCIPAL; goto error; } if (!(name = get_clnt_name(rqstp))) { ret.code = KADM5_FAILURE; goto error; } if (cmp_gss_krb5_name(handle, name, 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)) && kadm5int_acl_check(handle->context, name, ACL_CHANGEPW, arg->princ, NULL)) { ret.code = kadm5_randkey_principal_3((void *)handle, arg->princ, arg->keepold, arg->n_ks_tuple, arg->ks_tuple, &k, &nkeys); } else { log_unauth(funcname, prime_arg, client_name, service_name, client_addr(rqstp, buf)); ret.code = KADM5_AUTH_CHANGEPW; } if(ret.code == KADM5_OK) { if (handle->api_version == KADM5_API_VERSION_1) { krb5_copy_keyblock_contents(handle->context, k, &ret.key); krb5_free_keyblock(handle->context, k); } else { ret.keys = k; ret.n_keys = nkeys; } } if(ret.code != KADM5_AUTH_CHANGEPW) { /* Solaris Kerberos: Better error messages */ log_done(funcname, prime_arg, ((ret.code == 0) ? "success" : krb5_get_error_message(handle->context, ret.code)), client_name, service_name, client_addr(rqstp, buf)); } error: if (name) gss_release_name(&min_stat, &name); free_server_handle(handle); if (client_name) free(client_name); if (service_name) free(service_name); if (prime_arg) free(prime_arg); return (&ret); } generic_ret * create_policy_1_svc(cpol_arg *arg, struct svc_req *rqstp) { static generic_ret ret; char *prime_arg = NULL; char *client_name = NULL, *service_name = NULL; OM_uint32 min_stat; kadm5_server_handle_t handle; gss_name_t name = NULL; xdr_free(xdr_generic_ret, (char *) &ret); if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle))) return &ret; if ((ret.code = check_handle((void *)handle))) goto error; ret.api_version = handle->api_version; if (setup_gss_names(rqstp, &client_name, &service_name) < 0) { ret.code = KADM5_FAILURE; goto error; } prime_arg = arg->rec.policy; if (!(name = get_clnt_name(rqstp))) { ret.code = KADM5_FAILURE; goto error; } if (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context, name, ACL_ADD, NULL, NULL)) { ret.code = KADM5_AUTH_ADD; audit_kadmind_unauth(rqstp->rq_xprt, l_port, "kadm5_create_policy", prime_arg, client_name); log_unauth("kadm5_create_policy", prime_arg, client_name, service_name, client_addr(rqstp, buf)); } else { ret.code = kadm5_create_policy((void *)handle, &arg->rec, arg->mask); audit_kadmind_auth(rqstp->rq_xprt, l_port, "kadm5_create_policy", prime_arg, client_name, ret.code); log_done("kadm5_create_policy", ((prime_arg == NULL) ? "(null)" : prime_arg), ((ret.code == 0) ? "success" : error_message(ret.code)), client_name, service_name, client_addr(rqstp, buf)); } error: if (name) gss_release_name(&min_stat, &name); free_server_handle(handle); if (client_name) free(client_name); if (service_name) free(service_name); return &ret; } generic_ret * delete_policy_1_svc(dpol_arg *arg, struct svc_req *rqstp) { static generic_ret ret; char *prime_arg = NULL; char *client_name = NULL, *service_name = NULL; OM_uint32 min_stat; kadm5_server_handle_t handle; gss_name_t name = NULL; xdr_free(xdr_generic_ret, (char *) &ret); if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle))) return &ret; if ((ret.code = check_handle((void *)handle))) goto error; ret.api_version = handle->api_version; if (setup_gss_names(rqstp, &client_name, &service_name) < 0) { ret.code = KADM5_FAILURE; goto error; } prime_arg = arg->name; if (!(name = get_clnt_name(rqstp))) { ret.code = KADM5_FAILURE; goto error; } if (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context, name, ACL_DELETE, NULL, NULL)) { audit_kadmind_unauth(rqstp->rq_xprt, l_port, "kadm5_delete_policy", prime_arg, client_name); log_unauth("kadm5_delete_policy", prime_arg, client_name, service_name, client_addr(rqstp, buf)); ret.code = KADM5_AUTH_DELETE; } else { ret.code = kadm5_delete_policy((void *)handle, arg->name); audit_kadmind_auth(rqstp->rq_xprt, l_port, "kadm5_delete_policy", prime_arg, client_name, ret.code); log_done("kadm5_delete_policy", ((prime_arg == NULL) ? "(null)" : prime_arg), ((ret.code == 0) ? "success" : error_message(ret.code)), client_name, service_name, client_addr(rqstp, buf)); } error: if (name) gss_release_name(&min_stat, &name); free_server_handle(handle); if (client_name) free(client_name); if (service_name) free(service_name); return &ret; } generic_ret * modify_policy_1_svc(mpol_arg *arg, struct svc_req *rqstp) { static generic_ret ret; char *prime_arg = NULL; char *client_name = NULL, *service_name = NULL; OM_uint32 min_stat; kadm5_server_handle_t handle; gss_name_t name = NULL; xdr_free(xdr_generic_ret, (char *) &ret); if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle))) return &ret; if ((ret.code = check_handle((void *)handle))) goto error; ret.api_version = handle->api_version; if (setup_gss_names(rqstp, &client_name, &service_name) < 0) { ret.code = KADM5_FAILURE; goto error; } prime_arg = arg->rec.policy; if (!(name = get_clnt_name(rqstp))) { ret.code = KADM5_FAILURE; goto error; } if (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context, name, ACL_MODIFY, NULL, NULL)) { audit_kadmind_unauth(rqstp->rq_xprt, l_port, "kadm5_modify_policy", prime_arg, client_name); log_unauth("kadm5_modify_policy", prime_arg, client_name, service_name, client_addr(rqstp, buf)); ret.code = KADM5_AUTH_MODIFY; } else { ret.code = kadm5_modify_policy((void *)handle, &arg->rec, arg->mask); audit_kadmind_auth(rqstp->rq_xprt, l_port, "kadm5_modify_policy", prime_arg, client_name, ret.code); log_done("kadm5_modify_policy", ((prime_arg == NULL) ? "(null)" : prime_arg), ((ret.code == 0) ? "success" : error_message(ret.code)), client_name, service_name, client_addr(rqstp, buf)); } error: if (name) gss_release_name(&min_stat, &name); free_server_handle(handle); if (client_name) free(client_name); if (service_name) free(service_name); return (&ret); } gpol_ret * get_policy_1_svc(gpol_arg *arg, struct svc_req *rqstp) { static gpol_ret ret; kadm5_ret_t ret2; char *prime_arg = NULL, *funcname; char *client_name = NULL, *service_name = NULL; OM_uint32 min_stat; kadm5_policy_ent_t e; kadm5_principal_ent_rec caller_ent; krb5_principal caller; kadm5_server_handle_t handle; gss_name_t name = NULL; xdr_free(xdr_gpol_ret, (char *) &ret); if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle))) return &ret; if ((ret.code = check_handle((void *) handle))) goto error; ret.api_version = handle->api_version; funcname = handle->api_version == KADM5_API_VERSION_1 ? "kadm5_get_policy (V1)" : "kadm5_get_policy"; if (setup_gss_names(rqstp, &client_name, &service_name) < 0) { ret.code = KADM5_FAILURE; goto error; } prime_arg = arg->name; ret.code = KADM5_AUTH_GET; if (!(name = get_clnt_name(rqstp))) { ret.code = KADM5_FAILURE; goto error; } if (!CHANGEPW_SERVICE(rqstp) && kadm5int_acl_check(handle->context, name, ACL_INQUIRE, NULL, NULL)) ret.code = KADM5_OK; else { ret.code = kadm5_get_principal(handle->lhandle, handle->current_caller, &caller_ent, KADM5_PRINCIPAL_NORMAL_MASK); if (ret.code == KADM5_OK) { if (caller_ent.aux_attributes & KADM5_POLICY && strcmp(caller_ent.policy, arg->name) == 0) { ret.code = KADM5_OK; } else ret.code = KADM5_AUTH_GET; ret2 = kadm5_free_principal_ent(handle->lhandle, &caller_ent); ret.code = ret.code ? ret.code : ret2; } } if (ret.code == KADM5_OK) { if (handle->api_version == KADM5_API_VERSION_1) { ret.code = kadm5_get_policy_v1((void *)handle, arg->name, &e); if(ret.code == KADM5_OK) { memcpy(&ret.rec, e, sizeof(kadm5_policy_ent_rec)); free(e); } } else { ret.code = kadm5_get_policy((void *)handle, arg->name, &ret.rec); } audit_kadmind_auth(rqstp->rq_xprt, l_port, funcname, prime_arg, client_name, ret.code); log_done(funcname, ((prime_arg == NULL) ? "(null)" : prime_arg), ((ret.code == 0) ? "success" : error_message(ret.code)), client_name, service_name, client_addr(rqstp, buf)); } else { audit_kadmind_unauth(rqstp->rq_xprt, l_port, funcname, prime_arg, client_name); log_unauth(funcname, prime_arg, client_name, service_name, client_addr(rqstp, buf)); } error: if (name) gss_release_name(&min_stat, &name); free_server_handle(handle); if (client_name) free(client_name); if (service_name) free(service_name); return (&ret); } gpols_ret * get_pols_1_svc(gpols_arg *arg, struct svc_req *rqstp) { static gpols_ret ret; char *prime_arg = NULL; char *client_name = NULL, *service_name = NULL; OM_uint32 min_stat; kadm5_server_handle_t handle; gss_name_t name = NULL; xdr_free(xdr_gpols_ret, (char *) &ret); if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle))) return &ret; if ((ret.code = check_handle((void *)handle))) goto error; ret.api_version = handle->api_version; if (setup_gss_names(rqstp, &client_name, &service_name) < 0) { ret.code = KADM5_FAILURE; goto error; } prime_arg = arg->exp; if (prime_arg == NULL) prime_arg = "*"; if (!(name = get_clnt_name(rqstp))) { ret.code = KADM5_FAILURE; goto error; } if (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context, name, ACL_LIST, NULL, NULL)) { ret.code = KADM5_AUTH_LIST; audit_kadmind_unauth(rqstp->rq_xprt, l_port, "kadm5_get_policies", prime_arg, client_name); log_unauth("kadm5_get_policies", prime_arg, client_name, service_name, client_addr(rqstp, buf)); } else { ret.code = kadm5_get_policies((void *)handle, arg->exp, &ret.pols, &ret.count); audit_kadmind_auth(rqstp->rq_xprt, l_port, "kadm5_get_policies", prime_arg, client_name, ret.code); log_done("kadm5_get_policies", prime_arg, ((ret.code == 0) ? "success" : error_message(ret.code)), client_name, service_name, client_addr(rqstp, buf)); } error: if (name) gss_release_name(&min_stat, &name); free_server_handle(handle); if (client_name) free(client_name); if (service_name) free(service_name); return (&ret); } getprivs_ret * get_privs_1_svc(krb5_ui_4 *arg, struct svc_req *rqstp) { static getprivs_ret ret; char *client_name = NULL, *service_name = NULL; OM_uint32 min_stat; kadm5_server_handle_t handle; gss_name_t name = NULL; xdr_free(xdr_getprivs_ret, (char *) &ret); if ((ret.code = new_server_handle(*arg, rqstp, &handle))) return &ret; if ((ret.code = check_handle((void *)handle))) goto error; ret.api_version = handle->api_version; if (setup_gss_names(rqstp, &client_name, &service_name) < 0) { ret.code = KADM5_FAILURE; goto error; } if (!(name = get_clnt_name(rqstp))) { ret.code = KADM5_FAILURE; goto error; } ret.code = __kadm5_get_priv((void *) handle, &ret.privs, name); audit_kadmind_auth(rqstp->rq_xprt, l_port, "kadm5_get_privs", NULL, client_name, ret.code); log_done("kadm5_get_privs", client_name, ((ret.code == 0) ? "success" : error_message(ret.code)), client_name, service_name, client_addr(rqstp, buf)); error: if (name) gss_release_name(&min_stat, &name); free_server_handle(handle); if (client_name) free(client_name); if (service_name) free(service_name); return (&ret); } generic_ret *init_1_svc(krb5_ui_4 *arg, struct svc_req *rqstp) { static generic_ret ret; char *client_name, *service_name; kadm5_server_handle_t handle; size_t clen, slen; char *cdots, *sdots; xdr_free(xdr_generic_ret, (char *) &ret); if ((ret.code = new_server_handle(*arg, rqstp, &handle))) return &ret; if (! (ret.code = check_handle((void *)handle))) { ret.api_version = handle->api_version; } free_server_handle(handle); if (setup_gss_names(rqstp, &client_name, &service_name) < 0) { ret.code = KADM5_FAILURE; return &ret; } audit_kadmind_auth(rqstp->rq_xprt, l_port, (ret.api_version == KADM5_API_VERSION_1 ? "kadm5_init (V1)" : "kadm5_init"), NULL, client_name, ret.code); clen = strlen(client_name); trunc_name(&clen, &cdots); slen = strlen(service_name); trunc_name(&slen, &sdots); krb5_klog_syslog(LOG_NOTICE, "Request %s, %.*s%s, %s, " "client=%.*s%s, service=%.*s%s, addr=%s, flavor=%d", (ret.api_version == KADM5_API_VERSION_1 ? "kadm5_init (V1)" : "kadm5_init"), clen, client_name, cdots, (ret.code == 0) ? "success" : error_message(ret.code), clen, client_name, cdots, slen, service_name, sdots, client_addr(rqstp, buf), rqstp->rq_cred.oa_flavor); free(client_name); free(service_name); return (&ret); }