Home | History | Annotate | Download | only in server
      1 /*
      2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
      3  * Use is subject to license terms.
      4  */
      5 
      6 
      7 /*
      8  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
      9  *
     10  *	Openvision retains the copyright to derivative works of
     11  *	this source code.  Do *NOT* create a derivative of this
     12  *	source code before consulting with your legal department.
     13  *	Do *NOT* integrate *ANY* of this source code into another
     14  *	product before consulting with your legal department.
     15  *
     16  *	For further information, read the top-level Openvision
     17  *	copyright which is contained in the top-level MIT Kerberos
     18  *	copyright.
     19  *
     20  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
     21  *
     22  */
     23 
     24 
     25 /*
     26  * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
     27  *
     28  */
     29 
     30 #include    <k5-int.h>
     31 #include    <krb5/kdb.h>
     32 #include    <kadm5/server_internal.h>
     33 #include    "misc.h"
     34 
     35 /*
     36  * Function: chpass_principal_wrapper_3
     37  *
     38  * Purpose: wrapper to kadm5_chpass_principal that checks to see if
     39  *	    pw_min_life has been reached. if not it returns an error.
     40  *	    otherwise it calls kadm5_chpass_principal
     41  *
     42  * Arguments:
     43  *	principal	(input) krb5_principals whose password we are
     44  *				changing
     45  *	keepold 	(input) whether to preserve old keys
     46  *	n_ks_tuple	(input) the number of key-salt tuples in ks_tuple
     47  *	ks_tuple	(input) array of tuples indicating the caller's
     48  *				requested enctypes/salttypes
     49  *	password	(input) password we are going to change to.
     50  * 	<return value>	0 on success error code on failure.
     51  *
     52  * Requires:
     53  *	kadm5_init to have been run.
     54  *
     55  * Effects:
     56  *	calls kadm5_chpass_principal which changes the kdb and the
     57  *	the admin db.
     58  *
     59  */
     60 kadm5_ret_t
     61 chpass_principal_wrapper_3(void *server_handle,
     62 			   krb5_principal principal,
     63 			   krb5_boolean keepold,
     64 			   int n_ks_tuple,
     65 			   krb5_key_salt_tuple *ks_tuple,
     66 			   char *password)
     67 {
     68     kadm5_ret_t			ret;
     69 
     70     ret = check_min_life(server_handle, principal, NULL, 0);
     71     if (ret)
     72 	 return ret;
     73 
     74     return kadm5_chpass_principal_3(server_handle, principal,
     75 				    keepold, n_ks_tuple, ks_tuple,
     76 				    password);
     77 }
     78 
     79 
     80 /*
     81  * Function: randkey_principal_wrapper_3
     82  *
     83  * Purpose: wrapper to kadm5_randkey_principal which checks the
     84  *	    password's min. life.
     85  *
     86  * Arguments:
     87  *	principal	    (input) krb5_principal whose password we are
     88  *				    changing
     89  *	keepold 	(input) whether to preserve old keys
     90  *	n_ks_tuple	(input) the number of key-salt tuples in ks_tuple
     91  *	ks_tuple	(input) array of tuples indicating the caller's
     92  *				requested enctypes/salttypes
     93  *	key		    (output) new random key
     94  * 	<return value>	    0, error code on error.
     95  *
     96  * Requires:
     97  *	kadm5_init	 needs to be run
     98  *
     99  * Effects:
    100  *	calls kadm5_randkey_principal
    101  *
    102  */
    103 kadm5_ret_t
    104 randkey_principal_wrapper_3(void *server_handle,
    105 			    krb5_principal principal,
    106 			    krb5_boolean keepold,
    107 			    int n_ks_tuple,
    108 			    krb5_key_salt_tuple *ks_tuple,
    109 			    krb5_keyblock **keys, int *n_keys)
    110 {
    111     kadm5_ret_t			ret;
    112 
    113     ret = check_min_life(server_handle, principal, NULL, 0);
    114     if (ret)
    115 	 return ret;
    116     return kadm5_randkey_principal_3(server_handle, principal,
    117 				     keepold, n_ks_tuple, ks_tuple,
    118 				     keys, n_keys);
    119 }
    120 
    121 kadm5_ret_t
    122 schpw_util_wrapper(void *server_handle, krb5_principal princ,
    123 		   char *new_pw, char **ret_pw,
    124 		   char *msg_ret, unsigned int msg_len)
    125 {
    126     kadm5_ret_t ret;
    127 
    128     ret = check_min_life(server_handle, princ, msg_ret, msg_len);
    129     if (ret)
    130 	return ret;
    131 
    132     return kadm5_chpass_principal_util(server_handle, princ,
    133 				       new_pw, ret_pw,
    134 				       msg_ret, msg_len);
    135 }
    136 
    137 kadm5_ret_t
    138 randkey_principal_wrapper(void *server_handle, krb5_principal princ,
    139 			  krb5_keyblock ** keys, int *n_keys)
    140 {
    141     kadm5_ret_t ret;
    142 
    143     ret = check_min_life(server_handle, princ, NULL, 0);
    144 	if (ret)
    145 	    return ret;
    146 
    147     return kadm5_randkey_principal(server_handle, princ, keys, n_keys);
    148 }
    149 
    150 kadm5_ret_t
    151 check_min_life(void *server_handle, krb5_principal principal,
    152 	       char *msg_ret, unsigned int msg_len)
    153 {
    154     krb5_int32			now;
    155     kadm5_ret_t			ret;
    156     kadm5_policy_ent_rec	pol;
    157     kadm5_principal_ent_rec	princ;
    158     kadm5_server_handle_t	handle = server_handle;
    159 
    160     if (msg_ret != NULL)
    161 	*msg_ret = '\0';
    162 
    163     ret = krb5_timeofday(handle->context, &now);
    164     if (ret)
    165 	return ret;
    166 
    167     ret = kadm5_get_principal(handle->lhandle, principal,
    168 			      &princ, KADM5_PRINCIPAL_NORMAL_MASK);
    169     if(ret)
    170 	 return ret;
    171     if(princ.aux_attributes & KADM5_POLICY) {
    172 	if((ret=kadm5_get_policy(handle->lhandle,
    173 				 princ.policy, &pol)) != KADM5_OK) {
    174 	    (void) kadm5_free_principal_ent(handle->lhandle, &princ);
    175 	    return ret;
    176 	}
    177 	if((now - princ.last_pwd_change) < pol.pw_min_life &&
    178 	   !(princ.attributes & KRB5_KDB_REQUIRES_PWCHANGE)) {
    179 	    if (msg_ret != NULL) {
    180 		time_t until;
    181 		char *time_string, *ptr, *errstr;
    182 
    183 		until = princ.last_pwd_change + pol.pw_min_life;
    184 
    185 		time_string = ctime(&until);
    186 		errstr = (char *)error_message(CHPASS_UTIL_PASSWORD_TOO_SOON);
    187 
    188 		if (strlen(errstr) + strlen(time_string) >= msg_len) {
    189 		    *errstr = '\0';
    190 		} else {
    191 		    if (*(ptr = &time_string[strlen(time_string)-1]) == '\n')
    192 			*ptr = '\0';
    193 		    sprintf(msg_ret, errstr, time_string);
    194 		}
    195 	    }
    196 
    197 	    (void) kadm5_free_policy_ent(handle->lhandle, &pol);
    198 	    (void) kadm5_free_principal_ent(handle->lhandle, &princ);
    199 	    return KADM5_PASS_TOOSOON;
    200 	}
    201 
    202 	ret = kadm5_free_policy_ent(handle->lhandle, &pol);
    203 	if (ret) {
    204 	    (void) kadm5_free_principal_ent(handle->lhandle, &princ);
    205 	    return ret;
    206         }
    207     }
    208 
    209     return kadm5_free_principal_ent(handle->lhandle, &princ);
    210 }
    211