1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* 3 * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved 4 * 5 */ 6 7 #include <k5-int.h> 8 #include <kdb.h> 9 #include <kadm5/server_internal.h> 10 #include "misc.h" 11 #include "auth.h" 12 #include "net-server.h" 13 kadm5_ret_t 14 schpw_util_wrapper(void *server_handle, 15 krb5_principal client, 16 krb5_principal target, 17 krb5_boolean initial_flag, 18 char *new_pw, char **ret_pw, 19 char *msg_ret, unsigned int msg_len) 20 { 21 kadm5_ret_t ret; 22 kadm5_server_handle_t handle = server_handle; 23 24 /* 25 * If no target is explicitly provided, then the target principal 26 * is the client principal. 27 */ 28 if (target == NULL) 29 target = client; 30 31 /* If the client is changing its own password, require it to use an initial 32 * ticket, and enforce the policy min_life. */ 33 if (krb5_principal_compare(handle->context, client, target)) { 34 if (!initial_flag) { 35 strlcpy(msg_ret, "Ticket must be derived from a password", 36 msg_len); 37 return KADM5_AUTH_INITIAL; 38 } 39 40 ret = check_min_life(server_handle, target, msg_ret, msg_len); 41 if (ret != 0) 42 return ret; 43 } 44 45 if (auth(handle->context, OP_CPW, client, target, 46 NULL, NULL, NULL, NULL, 0)) { 47 ret = kadm5_chpass_principal_util(server_handle, 48 target, 49 new_pw, ret_pw, 50 msg_ret, msg_len); 51 } else { 52 ret = KADM5_AUTH_CHANGEPW; 53 strlcpy(msg_ret, "Unauthorized request", msg_len); 54 } 55 56 return ret; 57 } 58 59 kadm5_ret_t 60 check_min_life(void *server_handle, krb5_principal principal, 61 char *msg_ret, unsigned int msg_len) 62 { 63 krb5_timestamp now; 64 kadm5_ret_t ret; 65 kadm5_policy_ent_rec pol; 66 kadm5_principal_ent_rec princ; 67 kadm5_server_handle_t handle = server_handle; 68 69 if (msg_ret != NULL) 70 *msg_ret = '\0'; 71 72 ret = krb5_timeofday(handle->context, &now); 73 if (ret) 74 return ret; 75 76 ret = kadm5_get_principal(handle->lhandle, principal, 77 &princ, KADM5_PRINCIPAL_NORMAL_MASK); 78 if(ret) 79 return ret; 80 if(princ.aux_attributes & KADM5_POLICY) { 81 /* Look up the policy. If it doesn't exist, treat this principal as if 82 * it had no policy. */ 83 if((ret=kadm5_get_policy(handle->lhandle, 84 princ.policy, &pol)) != KADM5_OK) { 85 (void) kadm5_free_principal_ent(handle->lhandle, &princ); 86 return (ret == KADM5_UNK_POLICY) ? 0 : ret; 87 } 88 if(ts_delta(now, princ.last_pwd_change) < pol.pw_min_life && 89 !(princ.attributes & KRB5_KDB_REQUIRES_PWCHANGE)) { 90 if (msg_ret != NULL) { 91 time_t until; 92 char *time_string, *ptr; 93 const char *errstr; 94 95 until = princ.last_pwd_change + pol.pw_min_life; 96 97 time_string = ctime(&until); 98 if (time_string == NULL) 99 time_string = "(error)"; 100 errstr = error_message(CHPASS_UTIL_PASSWORD_TOO_SOON); 101 102 if (strlen(errstr) + strlen(time_string) < msg_len) { 103 if (*(ptr = &time_string[strlen(time_string)-1]) == '\n') 104 *ptr = '\0'; 105 snprintf(msg_ret, msg_len, errstr, time_string); 106 } 107 } 108 109 (void) kadm5_free_policy_ent(handle->lhandle, &pol); 110 (void) kadm5_free_principal_ent(handle->lhandle, &princ); 111 return KADM5_PASS_TOOSOON; 112 } 113 114 ret = kadm5_free_policy_ent(handle->lhandle, &pol); 115 if (ret) { 116 (void) kadm5_free_principal_ent(handle->lhandle, &princ); 117 return ret; 118 } 119 } 120 121 return kadm5_free_principal_ent(handle->lhandle, &princ); 122 } 123 124 #define MAXPRINCLEN 125 125 126 void 127 trunc_name(size_t *len, char **dots) 128 { 129 *dots = *len > MAXPRINCLEN ? "..." : ""; 130 *len = *len > MAXPRINCLEN ? MAXPRINCLEN : *len; 131 } 132 133 krb5_error_code 134 make_toolong_error (void *handle, krb5_data **out) 135 { 136 krb5_error errpkt; 137 krb5_error_code retval; 138 krb5_data *scratch; 139 kadm5_server_handle_t server_handle = *(void **)handle; 140 141 retval = krb5_us_timeofday(server_handle->context, &errpkt.stime, &errpkt.susec); 142 if (retval) 143 return retval; 144 errpkt.error = KRB_ERR_FIELD_TOOLONG; 145 retval = krb5_build_principal(server_handle->context, &errpkt.server, 146 strlen(server_handle->params.realm), 147 server_handle->params.realm, 148 "kadmin", "changepw", NULL); 149 if (retval) 150 return retval; 151 errpkt.client = NULL; 152 errpkt.cusec = 0; 153 errpkt.ctime = 0; 154 errpkt.text.length = 0; 155 errpkt.text.data = 0; 156 errpkt.e_data.length = 0; 157 errpkt.e_data.data = 0; 158 scratch = malloc(sizeof(*scratch)); 159 if (scratch == NULL) 160 return ENOMEM; 161 retval = krb5_mk_error(server_handle->context, &errpkt, scratch); 162 if (retval) { 163 free(scratch); 164 return retval; 165 } 166 167 *out = scratch; 168 return 0; 169 } 170 171 krb5_context get_context(void *handle) 172 { 173 kadm5_server_handle_t server_handle = *(void **)handle; 174 return server_handle->context; 175 } 176