xref: /onnv-gate/usr/src/lib/gss_mechs/mech_krb5/krb5/os/changepw.c (revision 7934:6aeeafc994de)
11770Sgtb /*
21770Sgtb  * lib/krb5/os/changepw.c
31770Sgtb  *
41770Sgtb  * Copyright 1990,1999,2001 by the Massachusetts Institute of Technology.
51770Sgtb  * All Rights Reserved.
61770Sgtb  *
71770Sgtb  * Export of this software from the United States of America may
81770Sgtb  *   require a specific license from the United States Government.
91770Sgtb  *   It is the responsibility of any person or organization contemplating
101770Sgtb  *   export to obtain such a license before exporting.
111770Sgtb  *
121770Sgtb  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
131770Sgtb  * distribute this software and its documentation for any purpose and
141770Sgtb  * without fee is hereby granted, provided that the above copyright
151770Sgtb  * notice appear in all copies and that both that copyright notice and
161770Sgtb  * this permission notice appear in supporting documentation, and that
171770Sgtb  * the name of M.I.T. not be used in advertising or publicity pertaining
181770Sgtb  * to distribution of the software without specific, written prior
191770Sgtb  * permission.  Furthermore if you modify this software you must label
201770Sgtb  * your software as modified software and not distribute it in such a
211770Sgtb  * fashion that it might be confused with the original M.I.T. software.
221770Sgtb  * M.I.T. makes no representations about the suitability of
231770Sgtb  * this software for any purpose.  It is provided "as is" without express
241770Sgtb  * or implied warranty.
251770Sgtb  *
261770Sgtb  */
271770Sgtb /*
281770Sgtb  * krb5_set_password - Implements set password per RFC 3244
291770Sgtb  * Added by Paul W. Nelson, Thursby Software Systems, Inc.
30*7934SMark.Phalan@Sun.COM  * Modified by Todd Stecher, Isilon Systems, to use krb1.4 socket infrastructure
311770Sgtb  */
321770Sgtb 
331770Sgtb #include "fake-addrinfo.h"
341770Sgtb #include "k5-int.h"
351770Sgtb #include "os-proto.h"
36*7934SMark.Phalan@Sun.COM #include "cm.h"
371770Sgtb 
381770Sgtb #include <stdio.h>
391770Sgtb #include <errno.h>
401770Sgtb 
411770Sgtb #ifndef GETSOCKNAME_ARG3_TYPE
421770Sgtb #define GETSOCKNAME_ARG3_TYPE int
431770Sgtb #endif
441770Sgtb 
45*7934SMark.Phalan@Sun.COM struct sendto_callback_context {
46*7934SMark.Phalan@Sun.COM     krb5_context 	context;
47*7934SMark.Phalan@Sun.COM     krb5_auth_context 	auth_context;
48*7934SMark.Phalan@Sun.COM     krb5_principal 	set_password_for;
49*7934SMark.Phalan@Sun.COM     char 		*newpw;
50*7934SMark.Phalan@Sun.COM     krb5_data 		ap_req;
51*7934SMark.Phalan@Sun.COM };
52*7934SMark.Phalan@Sun.COM 
53*7934SMark.Phalan@Sun.COM 
541770Sgtb /*
551770Sgtb  * Wrapper function for the two backends
561770Sgtb  */
571770Sgtb 
581770Sgtb static krb5_error_code
krb5_locate_kpasswd(krb5_context context,const krb5_data * realm,struct addrlist * addrlist,krb5_boolean useTcp)591770Sgtb krb5_locate_kpasswd(krb5_context context, const krb5_data *realm,
60*7934SMark.Phalan@Sun.COM 		    struct addrlist *addrlist, krb5_boolean useTcp)
611770Sgtb {
621770Sgtb     krb5_error_code code;
63*7934SMark.Phalan@Sun.COM     int sockType = (useTcp ? SOCK_STREAM : SOCK_DGRAM);
641770Sgtb 
65*7934SMark.Phalan@Sun.COM     code = krb5int_locate_server (context, realm, addrlist,
66*7934SMark.Phalan@Sun.COM 				  locate_service_kpasswd, sockType, 0);
67*7934SMark.Phalan@Sun.COM 
681770Sgtb     if (code == KRB5_REALM_CANT_RESOLVE || code == KRB5_REALM_UNKNOWN) {
69*7934SMark.Phalan@Sun.COM 	code = krb5int_locate_server (context, realm, addrlist,
70*7934SMark.Phalan@Sun.COM 				      locate_service_kadmin, SOCK_STREAM, 0);
711770Sgtb 	if (!code) {
721770Sgtb 	    /* Success with admin_server but now we need to change the
73*7934SMark.Phalan@Sun.COM 	       port number to use DEFAULT_KPASSWD_PORT and the socktype.  */
741770Sgtb 	    int i;
75*7934SMark.Phalan@Sun.COM 	    for (i=0; i<addrlist->naddrs; i++) {
76*7934SMark.Phalan@Sun.COM 		struct addrinfo *a = addrlist->addrs[i].ai;
771770Sgtb 		if (a->ai_family == AF_INET)
781770Sgtb 		    sa2sin (a->ai_addr)->sin_port = htons(DEFAULT_KPASSWD_PORT);
79*7934SMark.Phalan@Sun.COM 		if (sockType != SOCK_STREAM)
80*7934SMark.Phalan@Sun.COM 		    a->ai_socktype = sockType;
811770Sgtb 	    }
821770Sgtb 	}
831770Sgtb     }
841770Sgtb     return (code);
851770Sgtb }
861770Sgtb 
871770Sgtb 
88*7934SMark.Phalan@Sun.COM /**
89*7934SMark.Phalan@Sun.COM  * This routine is used for a callback in sendto_kdc.c code. Simply
90*7934SMark.Phalan@Sun.COM  * put, we need the client addr to build the krb_priv portion of the
91*7934SMark.Phalan@Sun.COM  * password request.
92*7934SMark.Phalan@Sun.COM  */
93*7934SMark.Phalan@Sun.COM 
94*7934SMark.Phalan@Sun.COM 
kpasswd_sendto_msg_cleanup(void * callback_context,krb5_data * message)95*7934SMark.Phalan@Sun.COM static void kpasswd_sendto_msg_cleanup (void* callback_context, krb5_data* message)
96*7934SMark.Phalan@Sun.COM {
97*7934SMark.Phalan@Sun.COM     struct sendto_callback_context *ctx = callback_context;
98*7934SMark.Phalan@Sun.COM     krb5_free_data_contents(ctx->context, message);
99*7934SMark.Phalan@Sun.COM }
100*7934SMark.Phalan@Sun.COM 
101*7934SMark.Phalan@Sun.COM 
kpasswd_sendto_msg_callback(struct conn_state * conn,void * callback_context,krb5_data * message)102*7934SMark.Phalan@Sun.COM static int kpasswd_sendto_msg_callback(struct conn_state *conn, void *callback_context, krb5_data* message)
103*7934SMark.Phalan@Sun.COM {
104*7934SMark.Phalan@Sun.COM     krb5_error_code 			code = 0;
105*7934SMark.Phalan@Sun.COM     struct sockaddr_storage 		local_addr;
106*7934SMark.Phalan@Sun.COM     krb5_address 			local_kaddr;
107*7934SMark.Phalan@Sun.COM     struct sendto_callback_context	*ctx = callback_context;
108*7934SMark.Phalan@Sun.COM     GETSOCKNAME_ARG3_TYPE 		addrlen;
109*7934SMark.Phalan@Sun.COM     krb5_data				output;
110*7934SMark.Phalan@Sun.COM 
111*7934SMark.Phalan@Sun.COM     memset (message, 0, sizeof(krb5_data));
112*7934SMark.Phalan@Sun.COM 
113*7934SMark.Phalan@Sun.COM     /*
114*7934SMark.Phalan@Sun.COM      * We need the local addr from the connection socket
115*7934SMark.Phalan@Sun.COM      */
116*7934SMark.Phalan@Sun.COM     addrlen = sizeof(local_addr);
117*7934SMark.Phalan@Sun.COM 
118*7934SMark.Phalan@Sun.COM     if (getsockname(conn->fd, ss2sa(&local_addr), &addrlen) < 0) {
119*7934SMark.Phalan@Sun.COM 	code = SOCKET_ERRNO;
120*7934SMark.Phalan@Sun.COM 	goto cleanup;
121*7934SMark.Phalan@Sun.COM     }
122*7934SMark.Phalan@Sun.COM 
123*7934SMark.Phalan@Sun.COM     /* some brain-dead OS's don't return useful information from
124*7934SMark.Phalan@Sun.COM      * the getsockname call.  Namely, windows and solaris.  */
125*7934SMark.Phalan@Sun.COM 
126*7934SMark.Phalan@Sun.COM     if (ss2sin(&local_addr)->sin_addr.s_addr != 0) {
127*7934SMark.Phalan@Sun.COM 	local_kaddr.addrtype = ADDRTYPE_INET;
128*7934SMark.Phalan@Sun.COM 	local_kaddr.length = sizeof(ss2sin(&local_addr)->sin_addr);
129*7934SMark.Phalan@Sun.COM 	local_kaddr.contents = (krb5_octet *) &ss2sin(&local_addr)->sin_addr;
130*7934SMark.Phalan@Sun.COM     } else {
131*7934SMark.Phalan@Sun.COM 	krb5_address **addrs;
132*7934SMark.Phalan@Sun.COM 
133*7934SMark.Phalan@Sun.COM 	code = krb5_os_localaddr(ctx->context, &addrs);
134*7934SMark.Phalan@Sun.COM 	if (code)
135*7934SMark.Phalan@Sun.COM 	    goto cleanup;
136*7934SMark.Phalan@Sun.COM 
137*7934SMark.Phalan@Sun.COM 	local_kaddr.magic = addrs[0]->magic;
138*7934SMark.Phalan@Sun.COM 	local_kaddr.addrtype = addrs[0]->addrtype;
139*7934SMark.Phalan@Sun.COM 	local_kaddr.length = addrs[0]->length;
140*7934SMark.Phalan@Sun.COM 	local_kaddr.contents = malloc(addrs[0]->length);
141*7934SMark.Phalan@Sun.COM 	if (local_kaddr.contents == NULL && addrs[0]->length != 0) {
142*7934SMark.Phalan@Sun.COM 	    code = errno;
143*7934SMark.Phalan@Sun.COM 	    krb5_free_addresses(ctx->context, addrs);
144*7934SMark.Phalan@Sun.COM 	    goto cleanup;
145*7934SMark.Phalan@Sun.COM 	}
146*7934SMark.Phalan@Sun.COM 	memcpy(local_kaddr.contents, addrs[0]->contents, addrs[0]->length);
147*7934SMark.Phalan@Sun.COM 
148*7934SMark.Phalan@Sun.COM 	krb5_free_addresses(ctx->context, addrs);
149*7934SMark.Phalan@Sun.COM     }
150*7934SMark.Phalan@Sun.COM 
151*7934SMark.Phalan@Sun.COM 
152*7934SMark.Phalan@Sun.COM     /*
153*7934SMark.Phalan@Sun.COM      * TBD:  Does this tamper w/ the auth context in such a way
154*7934SMark.Phalan@Sun.COM      * to break us?  Yes - provide 1 per conn-state / host...
155*7934SMark.Phalan@Sun.COM      */
156*7934SMark.Phalan@Sun.COM 
157*7934SMark.Phalan@Sun.COM 
158*7934SMark.Phalan@Sun.COM     if ((code = krb5_auth_con_setaddrs(ctx->context, ctx->auth_context,
159*7934SMark.Phalan@Sun.COM 				       &local_kaddr, NULL)))
160*7934SMark.Phalan@Sun.COM 	goto cleanup;
161*7934SMark.Phalan@Sun.COM 
162*7934SMark.Phalan@Sun.COM     if (ctx->set_password_for)
163*7934SMark.Phalan@Sun.COM 	code = krb5int_mk_setpw_req(ctx->context,
164*7934SMark.Phalan@Sun.COM 				    ctx->auth_context,
165*7934SMark.Phalan@Sun.COM 				    &ctx->ap_req,
166*7934SMark.Phalan@Sun.COM 				    ctx->set_password_for,
167*7934SMark.Phalan@Sun.COM 				    ctx->newpw,
168*7934SMark.Phalan@Sun.COM 				    &output);
169*7934SMark.Phalan@Sun.COM     else
170*7934SMark.Phalan@Sun.COM 	code = krb5int_mk_chpw_req(ctx->context,
171*7934SMark.Phalan@Sun.COM 				   ctx->auth_context,
172*7934SMark.Phalan@Sun.COM 				   &ctx->ap_req,
173*7934SMark.Phalan@Sun.COM 				   ctx->newpw,
174*7934SMark.Phalan@Sun.COM 				   &output);
175*7934SMark.Phalan@Sun.COM     if (code)
176*7934SMark.Phalan@Sun.COM 	goto cleanup;
177*7934SMark.Phalan@Sun.COM 
178*7934SMark.Phalan@Sun.COM     message->length = output.length;
179*7934SMark.Phalan@Sun.COM     message->data = output.data;
180*7934SMark.Phalan@Sun.COM 
181*7934SMark.Phalan@Sun.COM cleanup:
182*7934SMark.Phalan@Sun.COM     return code;
183*7934SMark.Phalan@Sun.COM }
184*7934SMark.Phalan@Sun.COM 
185*7934SMark.Phalan@Sun.COM 
1861770Sgtb /*
1871770Sgtb ** The logic for setting and changing a password is mostly the same
1881770Sgtb ** krb5_change_set_password handles both cases
1891770Sgtb **	if set_password_for is NULL, then a password change is performed,
1901770Sgtb **  otherwise, the password is set for the principal indicated in set_password_for
1911770Sgtb */
1921770Sgtb krb5_error_code KRB5_CALLCONV
krb5_change_set_password(krb5_context context,krb5_creds * creds,char * newpw,krb5_principal set_password_for,int * result_code,krb5_data * result_code_string,krb5_data * result_string)193*7934SMark.Phalan@Sun.COM krb5_change_set_password(krb5_context context, krb5_creds *creds, char *newpw,
194*7934SMark.Phalan@Sun.COM 			 krb5_principal set_password_for,
195*7934SMark.Phalan@Sun.COM 			 int *result_code, krb5_data *result_code_string,
196*7934SMark.Phalan@Sun.COM 			 krb5_data *result_string)
1971770Sgtb {
198*7934SMark.Phalan@Sun.COM     krb5_data 			chpw_rep;
199*7934SMark.Phalan@Sun.COM     krb5_address 		remote_kaddr;
200*7934SMark.Phalan@Sun.COM     krb5_boolean		useTcp = 0;
201*7934SMark.Phalan@Sun.COM     GETSOCKNAME_ARG3_TYPE 	addrlen;
202*7934SMark.Phalan@Sun.COM     krb5_error_code 		code = 0;
203*7934SMark.Phalan@Sun.COM     char 			*code_string;
204*7934SMark.Phalan@Sun.COM     int				local_result_code;
205*7934SMark.Phalan@Sun.COM 
206*7934SMark.Phalan@Sun.COM     struct sendto_callback_context  callback_ctx;
207*7934SMark.Phalan@Sun.COM     struct sendto_callback_info	callback_info;
208*7934SMark.Phalan@Sun.COM     struct sockaddr_storage	remote_addr;
209*7934SMark.Phalan@Sun.COM     struct addrlist 		al = ADDRLIST_INIT;
2101770Sgtb 
211*7934SMark.Phalan@Sun.COM     memset( &callback_ctx, 0, sizeof(struct sendto_callback_context));
212*7934SMark.Phalan@Sun.COM     callback_ctx.context = context;
213*7934SMark.Phalan@Sun.COM     callback_ctx.newpw = newpw;
214*7934SMark.Phalan@Sun.COM     callback_ctx.set_password_for = set_password_for;
2151770Sgtb 
216*7934SMark.Phalan@Sun.COM     if ((code = krb5_auth_con_init(callback_ctx.context,
217*7934SMark.Phalan@Sun.COM 				   &callback_ctx.auth_context)))
2181770Sgtb 	goto cleanup;
2191770Sgtb 
220*7934SMark.Phalan@Sun.COM     if ((code = krb5_mk_req_extended(callback_ctx.context,
221*7934SMark.Phalan@Sun.COM 				     &callback_ctx.auth_context,
222*7934SMark.Phalan@Sun.COM 				     AP_OPTS_USE_SUBKEY,
223*7934SMark.Phalan@Sun.COM 				     NULL,
224*7934SMark.Phalan@Sun.COM 				     creds,
225*7934SMark.Phalan@Sun.COM 				     &callback_ctx.ap_req)))
226*7934SMark.Phalan@Sun.COM 	goto cleanup;
2271770Sgtb 
228*7934SMark.Phalan@Sun.COM     do {
229*7934SMark.Phalan@Sun.COM 	if ((code = krb5_locate_kpasswd(callback_ctx.context,
230*7934SMark.Phalan@Sun.COM 					krb5_princ_realm(callback_ctx.context,
231*7934SMark.Phalan@Sun.COM 							 creds->server),
232*7934SMark.Phalan@Sun.COM 					&al, useTcp)))
233*7934SMark.Phalan@Sun.COM 	    break;
2341770Sgtb 
2351770Sgtb 	addrlen = sizeof(remote_addr);
236*7934SMark.Phalan@Sun.COM 
237*7934SMark.Phalan@Sun.COM 	callback_info.context = (void*) &callback_ctx;
238*7934SMark.Phalan@Sun.COM 	callback_info.pfn_callback = kpasswd_sendto_msg_callback;
239*7934SMark.Phalan@Sun.COM 	callback_info.pfn_cleanup = kpasswd_sendto_msg_cleanup;
2401770Sgtb 
241*7934SMark.Phalan@Sun.COM 	if ((code = krb5int_sendto(callback_ctx.context,
242*7934SMark.Phalan@Sun.COM 				   NULL,
243*7934SMark.Phalan@Sun.COM 				   &al,
244*7934SMark.Phalan@Sun.COM 				   &callback_info,
245*7934SMark.Phalan@Sun.COM 				   &chpw_rep,
246*7934SMark.Phalan@Sun.COM 				   NULL,
247*7934SMark.Phalan@Sun.COM 				   NULL,
248*7934SMark.Phalan@Sun.COM 				   ss2sa(&remote_addr),
249*7934SMark.Phalan@Sun.COM                                    &addrlen,
250*7934SMark.Phalan@Sun.COM 				   NULL,
251*7934SMark.Phalan@Sun.COM 				   NULL,
252*7934SMark.Phalan@Sun.COM 				   NULL
253*7934SMark.Phalan@Sun.COM 		 ))) {
254*7934SMark.Phalan@Sun.COM 
255*7934SMark.Phalan@Sun.COM 	    /*
256*7934SMark.Phalan@Sun.COM 	     * Here we may want to switch to TCP on some errors.
257*7934SMark.Phalan@Sun.COM 	     * right?
258*7934SMark.Phalan@Sun.COM 	     */
259*7934SMark.Phalan@Sun.COM 	    break;
2601770Sgtb 	}
2611770Sgtb 
2621770Sgtb 	remote_kaddr.addrtype = ADDRTYPE_INET;
2631770Sgtb 	remote_kaddr.length = sizeof(ss2sin(&remote_addr)->sin_addr);
2641770Sgtb 	remote_kaddr.contents = (krb5_octet *) &ss2sin(&remote_addr)->sin_addr;
2651770Sgtb 
266*7934SMark.Phalan@Sun.COM 	if ((code = krb5_auth_con_setaddrs(callback_ctx.context,
267*7934SMark.Phalan@Sun.COM 					   callback_ctx.auth_context,
268*7934SMark.Phalan@Sun.COM 					   NULL,
269*7934SMark.Phalan@Sun.COM 					   &remote_kaddr)))
270*7934SMark.Phalan@Sun.COM 	    break;
2711770Sgtb 
272*7934SMark.Phalan@Sun.COM 	if (set_password_for)
273*7934SMark.Phalan@Sun.COM 	    code = krb5int_rd_setpw_rep(callback_ctx.context,
274*7934SMark.Phalan@Sun.COM 					callback_ctx.auth_context,
275*7934SMark.Phalan@Sun.COM 					&chpw_rep,
276*7934SMark.Phalan@Sun.COM 					&local_result_code,
277*7934SMark.Phalan@Sun.COM 					result_string);
278*7934SMark.Phalan@Sun.COM 	else
279*7934SMark.Phalan@Sun.COM 	    code = krb5int_rd_chpw_rep(callback_ctx.context,
280*7934SMark.Phalan@Sun.COM 				       callback_ctx.auth_context,
281*7934SMark.Phalan@Sun.COM 				       &chpw_rep,
282*7934SMark.Phalan@Sun.COM 				       &local_result_code,
283*7934SMark.Phalan@Sun.COM 				       result_string);
2841770Sgtb 
285*7934SMark.Phalan@Sun.COM 	if (code) {
286*7934SMark.Phalan@Sun.COM 	    if (code == KRB5KRB_ERR_RESPONSE_TOO_BIG && !useTcp ) {
287*7934SMark.Phalan@Sun.COM 		krb5int_free_addrlist (&al);
288*7934SMark.Phalan@Sun.COM 		useTcp = 1;
289*7934SMark.Phalan@Sun.COM 		continue;
290*7934SMark.Phalan@Sun.COM 	    }
2911770Sgtb 
292*7934SMark.Phalan@Sun.COM 	    break;
293*7934SMark.Phalan@Sun.COM 	}
2941770Sgtb 
2951770Sgtb 	if (result_code)
2961770Sgtb 	    *result_code = local_result_code;
297*7934SMark.Phalan@Sun.COM 
2981770Sgtb 	if (result_code_string) {
299*7934SMark.Phalan@Sun.COM 	    if (set_password_for)
300*7934SMark.Phalan@Sun.COM 		code = krb5int_setpw_result_code_string(callback_ctx.context,
301*7934SMark.Phalan@Sun.COM 							local_result_code,
302*7934SMark.Phalan@Sun.COM 							(const char **)&code_string);
303*7934SMark.Phalan@Sun.COM 	    else
304*7934SMark.Phalan@Sun.COM 		code = krb5_chpw_result_code_string(callback_ctx.context,
305*7934SMark.Phalan@Sun.COM 						    local_result_code,
306*7934SMark.Phalan@Sun.COM 						    &code_string);
307*7934SMark.Phalan@Sun.COM 	    if(code)
308*7934SMark.Phalan@Sun.COM 		goto cleanup;
3091770Sgtb 
3101770Sgtb 	    result_code_string->length = strlen(code_string);
3111770Sgtb 	    result_code_string->data = malloc(result_code_string->length);
3121770Sgtb 	    if (result_code_string->data == NULL) {
3131770Sgtb 		code = ENOMEM;
3141770Sgtb 		goto cleanup;
3151770Sgtb 	    }
3161770Sgtb 	    strncpy(result_code_string->data, code_string, result_code_string->length);
3171770Sgtb 	}
3181770Sgtb 
319*7934SMark.Phalan@Sun.COM 	if (code == KRB5KRB_ERR_RESPONSE_TOO_BIG && !useTcp ) {
320*7934SMark.Phalan@Sun.COM 	    krb5int_free_addrlist (&al);
321*7934SMark.Phalan@Sun.COM 	    useTcp = 1;
322*7934SMark.Phalan@Sun.COM         } else {
323*7934SMark.Phalan@Sun.COM 	    break;
324*7934SMark.Phalan@Sun.COM 	}
325*7934SMark.Phalan@Sun.COM     } while (TRUE);
3261770Sgtb 
3271770Sgtb cleanup:
328*7934SMark.Phalan@Sun.COM     if (callback_ctx.auth_context != NULL)
329*7934SMark.Phalan@Sun.COM 	krb5_auth_con_free(callback_ctx.context, callback_ctx.auth_context);
3301770Sgtb 
3311770Sgtb     krb5int_free_addrlist (&al);
332*7934SMark.Phalan@Sun.COM     krb5_free_data_contents(callback_ctx.context, &callback_ctx.ap_req);
3331770Sgtb 
3341770Sgtb     return(code);
3351770Sgtb }
3361770Sgtb 
3371770Sgtb krb5_error_code KRB5_CALLCONV
krb5_change_password(krb5_context context,krb5_creds * creds,char * newpw,int * result_code,krb5_data * result_code_string,krb5_data * result_string)3381770Sgtb krb5_change_password(krb5_context context, krb5_creds *creds, char *newpw, int *result_code, krb5_data *result_code_string, krb5_data *result_string)
3391770Sgtb {
3401770Sgtb 	return krb5_change_set_password(
3411770Sgtb 		context, creds, newpw, NULL, result_code, result_code_string, result_string );
3421770Sgtb }
3431770Sgtb 
3441770Sgtb /*
3451770Sgtb  * krb5_set_password - Implements set password per RFC 3244
3461770Sgtb  *
3471770Sgtb  */
3481770Sgtb 
3491770Sgtb krb5_error_code KRB5_CALLCONV
krb5_set_password(krb5_context context,krb5_creds * creds,char * newpw,krb5_principal change_password_for,int * result_code,krb5_data * result_code_string,krb5_data * result_string)3501770Sgtb krb5_set_password(
3511770Sgtb 	krb5_context context,
3521770Sgtb 	krb5_creds *creds,
3531770Sgtb 	char *newpw,
3541770Sgtb 	krb5_principal change_password_for,
3551770Sgtb 	int *result_code, krb5_data *result_code_string, krb5_data *result_string
3561770Sgtb 	)
3571770Sgtb {
3581770Sgtb 	return krb5_change_set_password(
3591770Sgtb 		context, creds, newpw, change_password_for, result_code, result_code_string, result_string );
3601770Sgtb }
3611770Sgtb 
3621770Sgtb krb5_error_code KRB5_CALLCONV
krb5_set_password_using_ccache(krb5_context context,krb5_ccache ccache,char * newpw,krb5_principal change_password_for,int * result_code,krb5_data * result_code_string,krb5_data * result_string)3631770Sgtb krb5_set_password_using_ccache(
3641770Sgtb 	krb5_context context,
3651770Sgtb 	krb5_ccache ccache,
3661770Sgtb 	char *newpw,
3671770Sgtb 	krb5_principal change_password_for,
3681770Sgtb 	int *result_code, krb5_data *result_code_string, krb5_data *result_string
3691770Sgtb 	)
3701770Sgtb {
371*7934SMark.Phalan@Sun.COM     krb5_creds		creds;
372*7934SMark.Phalan@Sun.COM     krb5_creds		*credsp;
373*7934SMark.Phalan@Sun.COM     krb5_error_code	code;
3741770Sgtb 
375*7934SMark.Phalan@Sun.COM     /*
376*7934SMark.Phalan@Sun.COM     ** get the proper creds for use with krb5_set_password -
377*7934SMark.Phalan@Sun.COM     */
378*7934SMark.Phalan@Sun.COM     memset (&creds, 0, sizeof(creds));
379*7934SMark.Phalan@Sun.COM     /*
380*7934SMark.Phalan@Sun.COM     ** first get the principal for the password service -
381*7934SMark.Phalan@Sun.COM     */
382*7934SMark.Phalan@Sun.COM     code = krb5_cc_get_principal (context, ccache, &creds.client);
383*7934SMark.Phalan@Sun.COM     if (!code) {
384*7934SMark.Phalan@Sun.COM 	code = krb5_build_principal(context, &creds.server,
385*7934SMark.Phalan@Sun.COM 				    krb5_princ_realm(context, change_password_for)->length,
386*7934SMark.Phalan@Sun.COM 				    krb5_princ_realm(context, change_password_for)->data,
387*7934SMark.Phalan@Sun.COM 				    "kadmin", "changepw", NULL);
388*7934SMark.Phalan@Sun.COM 	if (!code) {
389*7934SMark.Phalan@Sun.COM 	    code = krb5_get_credentials(context, 0, ccache, &creds, &credsp);
390*7934SMark.Phalan@Sun.COM 	    if (!code) {
391*7934SMark.Phalan@Sun.COM 		code = krb5_set_password(context, credsp, newpw, change_password_for,
392*7934SMark.Phalan@Sun.COM 					 result_code, result_code_string,
393*7934SMark.Phalan@Sun.COM 					 result_string);
394*7934SMark.Phalan@Sun.COM 		krb5_free_creds(context, credsp);
395*7934SMark.Phalan@Sun.COM 	    }
3961770Sgtb 	}
397*7934SMark.Phalan@Sun.COM 	krb5_free_cred_contents(context, &creds);
398*7934SMark.Phalan@Sun.COM     }
399*7934SMark.Phalan@Sun.COM     return code;
4001770Sgtb }
401