xref: /onnv-gate/usr/src/lib/krb5/kadm5/chpass_util.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
3*0Sstevel@tonic-gate  * Use is subject to license terms.
4*0Sstevel@tonic-gate  */
5*0Sstevel@tonic-gate 
6*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
7*0Sstevel@tonic-gate 
8*0Sstevel@tonic-gate /*
9*0Sstevel@tonic-gate  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
10*0Sstevel@tonic-gate  *
11*0Sstevel@tonic-gate  *	Openvision retains the copyright to derivative works of
12*0Sstevel@tonic-gate  *	this source code.  Do *NOT* create a derivative of this
13*0Sstevel@tonic-gate  *	source code before consulting with your legal department.
14*0Sstevel@tonic-gate  *	Do *NOT* integrate *ANY* of this source code into another
15*0Sstevel@tonic-gate  *	product before consulting with your legal department.
16*0Sstevel@tonic-gate  *
17*0Sstevel@tonic-gate  *	For further information, read the top-level Openvision
18*0Sstevel@tonic-gate  *	copyright which is contained in the top-level MIT Kerberos
19*0Sstevel@tonic-gate  *	copyright.
20*0Sstevel@tonic-gate  *
21*0Sstevel@tonic-gate  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
22*0Sstevel@tonic-gate  *
23*0Sstevel@tonic-gate  */
24*0Sstevel@tonic-gate 
25*0Sstevel@tonic-gate 
26*0Sstevel@tonic-gate /*
27*0Sstevel@tonic-gate  * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
28*0Sstevel@tonic-gate  *
29*0Sstevel@tonic-gate  * $Header: /cvs/krbdev/krb5/src/lib/kadm5/chpass_util.c,v 1.18.18.1 2000/05/19 22:24:14 raeburn Exp $
30*0Sstevel@tonic-gate  *
31*0Sstevel@tonic-gate  *
32*0Sstevel@tonic-gate  */
33*0Sstevel@tonic-gate 
34*0Sstevel@tonic-gate 
35*0Sstevel@tonic-gate #include <stdio.h>
36*0Sstevel@tonic-gate #include <memory.h>
37*0Sstevel@tonic-gate #include <time.h>
38*0Sstevel@tonic-gate #include <locale.h>
39*0Sstevel@tonic-gate 
40*0Sstevel@tonic-gate #include <kadm5/admin.h>
41*0Sstevel@tonic-gate #include "admin_internal.h"
42*0Sstevel@tonic-gate 
43*0Sstevel@tonic-gate #include <krb5.h>
44*0Sstevel@tonic-gate 
45*0Sstevel@tonic-gate #define string_text error_message
46*0Sstevel@tonic-gate 
47*0Sstevel@tonic-gate const char *chpw_error_message(kadm5_ret_t code);
48*0Sstevel@tonic-gate 
49*0Sstevel@tonic-gate /*
50*0Sstevel@tonic-gate  * Function: kadm5_chpass_principal_util
51*0Sstevel@tonic-gate  *
52*0Sstevel@tonic-gate  * Purpose: Wrapper around chpass_principal. We can read new pw,
53*0Sstevel@tonic-gate  *          change pw and return useful messages
54*0Sstevel@tonic-gate  *
55*0Sstevel@tonic-gate  * Arguments:
56*0Sstevel@tonic-gate  *
57*0Sstevel@tonic-gate  *      princ          (input) a krb5b_principal structure for the
58*0Sstevel@tonic-gate  *                     principal whose password we should change.
59*0Sstevel@tonic-gate  *
60*0Sstevel@tonic-gate  *      new_password   (input) NULL or a null terminated string with the
61*0Sstevel@tonic-gate  *                     the principal's desired new password.  If new_password
62*0Sstevel@tonic-gate  *                     is NULL then this routine will read a new password.
63*0Sstevel@tonic-gate  *
64*0Sstevel@tonic-gate  *	pw_ret		(output) if non-NULL, points to a static buffer
65*0Sstevel@tonic-gate  *			containing the new password (if password is prompted
66*0Sstevel@tonic-gate  *			internally), or to the new_password argument (if
67*0Sstevel@tonic-gate  *			that is non-NULL).  If the former, then the buffer
68*0Sstevel@tonic-gate  *			is only valid until the next call to the function,
69*0Sstevel@tonic-gate  *			and the caller should be sure to zero it when
70*0Sstevel@tonic-gate  *			it is no longer needed.
71*0Sstevel@tonic-gate  *
72*0Sstevel@tonic-gate  *      msg_ret         (output) a useful message is copied here.
73*0Sstevel@tonic-gate  *
74*0Sstevel@tonic-gate  *      <return value>  exit status of 0 for success, else the com err code
75*0Sstevel@tonic-gate  *                      for the last significant routine called.
76*0Sstevel@tonic-gate  *
77*0Sstevel@tonic-gate  * Requires:
78*0Sstevel@tonic-gate  *
79*0Sstevel@tonic-gate  *      A msg_ret should point to a buffer large enough for the messasge.
80*0Sstevel@tonic-gate  *
81*0Sstevel@tonic-gate  * Effects:
82*0Sstevel@tonic-gate  *
83*0Sstevel@tonic-gate  * Modifies:
84*0Sstevel@tonic-gate  *
85*0Sstevel@tonic-gate  *
86*0Sstevel@tonic-gate  */
87*0Sstevel@tonic-gate 
88*0Sstevel@tonic-gate kadm5_ret_t _kadm5_chpass_principal_util(void *server_handle,
89*0Sstevel@tonic-gate 					 void *lhandle,
90*0Sstevel@tonic-gate 					 krb5_principal princ,
91*0Sstevel@tonic-gate 					 char *new_pw,
92*0Sstevel@tonic-gate 					 char **ret_pw,
93*0Sstevel@tonic-gate 					 char *msg_ret,
94*0Sstevel@tonic-gate 					 int msg_len)
95*0Sstevel@tonic-gate {
96*0Sstevel@tonic-gate   int code, code2;
97*0Sstevel@tonic-gate   unsigned int pwsize;
98*0Sstevel@tonic-gate   static char buffer[255];
99*0Sstevel@tonic-gate   char *new_password;
100*0Sstevel@tonic-gate   kadm5_principal_ent_rec princ_ent;
101*0Sstevel@tonic-gate   kadm5_policy_ent_rec policy_ent;
102*0Sstevel@tonic-gate 	krb5_chgpwd_prot passwd_protocol;
103*0Sstevel@tonic-gate 
104*0Sstevel@tonic-gate   _KADM5_CHECK_HANDLE(server_handle);
105*0Sstevel@tonic-gate 
106*0Sstevel@tonic-gate   if (ret_pw)
107*0Sstevel@tonic-gate     *ret_pw = NULL;
108*0Sstevel@tonic-gate 
109*0Sstevel@tonic-gate   if (new_pw != NULL) {
110*0Sstevel@tonic-gate     new_password = new_pw;
111*0Sstevel@tonic-gate   } else { /* read the password */
112*0Sstevel@tonic-gate     krb5_context context;
113*0Sstevel@tonic-gate 
114*0Sstevel@tonic-gate     if ((code = (int) krb5_init_context(&context)) == 0) {
115*0Sstevel@tonic-gate       pwsize = sizeof(buffer);
116*0Sstevel@tonic-gate 			code = krb5_read_password(context,
117*0Sstevel@tonic-gate 						KADM5_PW_FIRST_PROMPT,
118*0Sstevel@tonic-gate 				KADM5_PW_SECOND_PROMPT,
119*0Sstevel@tonic-gate 				buffer, &pwsize);
120*0Sstevel@tonic-gate       krb5_free_context(context);
121*0Sstevel@tonic-gate     }
122*0Sstevel@tonic-gate 
123*0Sstevel@tonic-gate     if (code == 0)
124*0Sstevel@tonic-gate       new_password = buffer;
125*0Sstevel@tonic-gate     else {
126*0Sstevel@tonic-gate #ifdef ZEROPASSWD
127*0Sstevel@tonic-gate       memset(buffer, 0, sizeof(buffer));
128*0Sstevel@tonic-gate #endif
129*0Sstevel@tonic-gate       if (code == KRB5_LIBOS_BADPWDMATCH) {
130*0Sstevel@tonic-gate 	strncpy(msg_ret, string_text(CHPASS_UTIL_NEW_PASSWORD_MISMATCH),
131*0Sstevel@tonic-gate 		msg_len - 1);
132*0Sstevel@tonic-gate 	msg_ret[msg_len - 1] = '\0';
133*0Sstevel@tonic-gate 	return(code);
134*0Sstevel@tonic-gate       } else {
135*0Sstevel@tonic-gate         strncpy(msg_ret, error_message(code), msg_len - 1);
136*0Sstevel@tonic-gate         strncat(msg_ret, " ", msg_len - 1);
137*0Sstevel@tonic-gate         strncat(msg_ret, string_text(CHPASS_UTIL_WHILE_READING_PASSWORD),
138*0Sstevel@tonic-gate 		msg_len - 1);
139*0Sstevel@tonic-gate         strncat(msg_ret, string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED),
140*0Sstevel@tonic-gate 		msg_len - 1);
141*0Sstevel@tonic-gate 	msg_ret[msg_len - 1] = '\0';
142*0Sstevel@tonic-gate 	return(code);
143*0Sstevel@tonic-gate       }
144*0Sstevel@tonic-gate     }
145*0Sstevel@tonic-gate     if (pwsize == 0) {
146*0Sstevel@tonic-gate #ifdef ZEROPASSWD
147*0Sstevel@tonic-gate       memset(buffer, 0, sizeof(buffer));
148*0Sstevel@tonic-gate #endif
149*0Sstevel@tonic-gate       strncpy(msg_ret, string_text(CHPASS_UTIL_NO_PASSWORD_READ), msg_len - 1);
150*0Sstevel@tonic-gate       msg_ret[msg_len - 1] = '\0';
151*0Sstevel@tonic-gate       return(KRB5_LIBOS_CANTREADPWD); /* could do better */
152*0Sstevel@tonic-gate     }
153*0Sstevel@tonic-gate   }
154*0Sstevel@tonic-gate 
155*0Sstevel@tonic-gate   if (ret_pw)
156*0Sstevel@tonic-gate     *ret_pw = new_password;
157*0Sstevel@tonic-gate 
158*0Sstevel@tonic-gate 	passwd_protocol = _kadm5_get_kpasswd_protocol(server_handle);
159*0Sstevel@tonic-gate 	if (passwd_protocol == KRB5_CHGPWD_CHANGEPW_V2) {
160*0Sstevel@tonic-gate 		kadm5_ret_t srvr_rsp_code;
161*0Sstevel@tonic-gate 		krb5_data   srvr_msg;
162*0Sstevel@tonic-gate 
163*0Sstevel@tonic-gate 		srvr_msg.length = 0;
164*0Sstevel@tonic-gate 		srvr_msg.data = NULL;
165*0Sstevel@tonic-gate 
166*0Sstevel@tonic-gate 		code = kadm5_chpass_principal_v2(server_handle, princ,
167*0Sstevel@tonic-gate 						new_password,
168*0Sstevel@tonic-gate 						&srvr_rsp_code,
169*0Sstevel@tonic-gate 						&srvr_msg);
170*0Sstevel@tonic-gate 		if (srvr_rsp_code) {
171*0Sstevel@tonic-gate 			sprintf(msg_ret, "%s%s%.*s\n",
172*0Sstevel@tonic-gate 				chpw_error_message(srvr_rsp_code),
173*0Sstevel@tonic-gate 				srvr_msg.length? ": " : "",
174*0Sstevel@tonic-gate 				srvr_msg.length,
175*0Sstevel@tonic-gate 				srvr_msg.data ? srvr_msg.data : "");
176*0Sstevel@tonic-gate 
177*0Sstevel@tonic-gate 			return (srvr_rsp_code);
178*0Sstevel@tonic-gate 		}
179*0Sstevel@tonic-gate 		return (code);
180*0Sstevel@tonic-gate 
181*0Sstevel@tonic-gate 	} else if (passwd_protocol == KRB5_CHGPWD_RPCSEC) {
182*0Sstevel@tonic-gate 		code = kadm5_chpass_principal(server_handle, princ,
183*0Sstevel@tonic-gate 					    new_password);
184*0Sstevel@tonic-gate 
185*0Sstevel@tonic-gate #ifdef ZEROPASSWD
186*0Sstevel@tonic-gate   if (!ret_pw)
187*0Sstevel@tonic-gate 			memset(buffer, 0, sizeof (buffer));
188*0Sstevel@tonic-gate #endif
189*0Sstevel@tonic-gate 
190*0Sstevel@tonic-gate   if (code == KADM5_OK) {
191*0Sstevel@tonic-gate     strncpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_CHANGED), msg_len - 1);
192*0Sstevel@tonic-gate     msg_ret[msg_len - 1] = '\0';
193*0Sstevel@tonic-gate     return(0);
194*0Sstevel@tonic-gate   }
195*0Sstevel@tonic-gate 
196*0Sstevel@tonic-gate   if ((code != KADM5_PASS_Q_TOOSHORT) &&
197*0Sstevel@tonic-gate 		    (code != KADM5_PASS_REUSE) &&
198*0Sstevel@tonic-gate 		    (code != KADM5_PASS_Q_CLASS) &&
199*0Sstevel@tonic-gate 		    (code != KADM5_PASS_Q_DICT) &&
200*0Sstevel@tonic-gate 		    (code != KADM5_PASS_TOOSOON)) {
201*0Sstevel@tonic-gate     /* Can't get more info for other errors */
202*0Sstevel@tonic-gate     sprintf(buffer, "%s %s", error_message(code),
203*0Sstevel@tonic-gate 	    string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE));
204*0Sstevel@tonic-gate 			sprintf(msg_ret, "%s\n%s\n",
205*0Sstevel@tonic-gate 				string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED),
206*0Sstevel@tonic-gate 	    buffer);
207*0Sstevel@tonic-gate     return(code);
208*0Sstevel@tonic-gate   }
209*0Sstevel@tonic-gate 
210*0Sstevel@tonic-gate   /* Ok, we have a password quality error. Return a good message */
211*0Sstevel@tonic-gate 
212*0Sstevel@tonic-gate   if (code == KADM5_PASS_REUSE) {
213*0Sstevel@tonic-gate     strncpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_REUSE), msg_len - 1);
214*0Sstevel@tonic-gate     msg_ret[msg_len - 1] = '\0';
215*0Sstevel@tonic-gate     return(code);
216*0Sstevel@tonic-gate   }
217*0Sstevel@tonic-gate 
218*0Sstevel@tonic-gate   if (code == KADM5_PASS_Q_DICT) {
219*0Sstevel@tonic-gate     strncpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_IN_DICTIONARY),
220*0Sstevel@tonic-gate 	    msg_len - 1);
221*0Sstevel@tonic-gate     msg_ret[msg_len - 1] = '\0';
222*0Sstevel@tonic-gate     return(code);
223*0Sstevel@tonic-gate   }
224*0Sstevel@tonic-gate 
225*0Sstevel@tonic-gate   /* Look up policy for the remaining messages */
226*0Sstevel@tonic-gate 
227*0Sstevel@tonic-gate   code2 = kadm5_get_principal (lhandle, princ, &princ_ent,
228*0Sstevel@tonic-gate 			       KADM5_PRINCIPAL_NORMAL_MASK);
229*0Sstevel@tonic-gate   if (code2 != 0) {
230*0Sstevel@tonic-gate     strncpy(msg_ret, error_message(code2), msg_len - 1);
231*0Sstevel@tonic-gate     strncat(msg_ret, " ", msg_len - 1 - strlen(msg_ret));
232*0Sstevel@tonic-gate     strncat(msg_ret, string_text(CHPASS_UTIL_GET_PRINC_INFO), msg_len - 1 - strlen(msg_ret));
233*0Sstevel@tonic-gate     strncat(msg_ret, "\n", msg_len - 1 - strlen(msg_ret));
234*0Sstevel@tonic-gate     strncat(msg_ret, error_message(code), msg_len - 1 - strlen(msg_ret));
235*0Sstevel@tonic-gate     strncat(msg_ret, " ", msg_len - 1 - strlen(msg_ret));
236*0Sstevel@tonic-gate     strncat(msg_ret, string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE),
237*0Sstevel@tonic-gate 	    msg_len - 1 - strlen(msg_ret));
238*0Sstevel@tonic-gate     strncat(msg_ret, "\n\n", msg_len - 1 - strlen(msg_ret));
239*0Sstevel@tonic-gate     strncat(msg_ret, string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED),
240*0Sstevel@tonic-gate 	    msg_len - 1 - strlen(msg_ret));
241*0Sstevel@tonic-gate     strncat(msg_ret, "\n", msg_len - 1 - strlen(msg_ret));
242*0Sstevel@tonic-gate     msg_ret[msg_len - 1] = '\0';
243*0Sstevel@tonic-gate     return(code);
244*0Sstevel@tonic-gate   }
245*0Sstevel@tonic-gate 
246*0Sstevel@tonic-gate   if ((princ_ent.aux_attributes & KADM5_POLICY) == 0) {
247*0Sstevel@tonic-gate     strncpy(msg_ret, error_message(code), msg_len - 1 - strlen(msg_ret));
248*0Sstevel@tonic-gate     strncat(msg_ret, " ", msg_len - 1 - strlen(msg_ret));
249*0Sstevel@tonic-gate     strncpy(msg_ret, string_text(CHPASS_UTIL_NO_POLICY_YET_Q_ERROR),
250*0Sstevel@tonic-gate 	    msg_len - 1 - strlen(msg_ret));
251*0Sstevel@tonic-gate     strncat(msg_ret, "\n\n", msg_len - 1 - strlen(msg_ret));
252*0Sstevel@tonic-gate     strncpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED),
253*0Sstevel@tonic-gate 	    msg_len - 1 - strlen(msg_ret));
254*0Sstevel@tonic-gate     msg_ret[msg_len - 1] = '\0';
255*0Sstevel@tonic-gate 
256*0Sstevel@tonic-gate     (void) kadm5_free_principal_ent(lhandle, &princ_ent);
257*0Sstevel@tonic-gate     return(code);
258*0Sstevel@tonic-gate   }
259*0Sstevel@tonic-gate 
260*0Sstevel@tonic-gate   code2 = kadm5_get_policy(lhandle, princ_ent.policy,
261*0Sstevel@tonic-gate 			   &policy_ent);
262*0Sstevel@tonic-gate   if (code2 != 0) {
263*0Sstevel@tonic-gate 			sprintf(msg_ret, "%s %s\n%s %s\n\n%s\n ",
264*0Sstevel@tonic-gate 			error_message(code2),
265*0Sstevel@tonic-gate 	    string_text(CHPASS_UTIL_GET_POLICY_INFO),
266*0Sstevel@tonic-gate 	    error_message(code),
267*0Sstevel@tonic-gate 	    string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE),
268*0Sstevel@tonic-gate 	    string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED));
269*0Sstevel@tonic-gate     (void) kadm5_free_principal_ent(lhandle, &princ_ent);
270*0Sstevel@tonic-gate     return(code);
271*0Sstevel@tonic-gate   }
272*0Sstevel@tonic-gate 
273*0Sstevel@tonic-gate   if (code == KADM5_PASS_Q_TOOSHORT) {
274*0Sstevel@tonic-gate 			sprintf(msg_ret,
275*0Sstevel@tonic-gate 				string_text(CHPASS_UTIL_PASSWORD_TOO_SHORT),
276*0Sstevel@tonic-gate 	    policy_ent.pw_min_length);
277*0Sstevel@tonic-gate     (void) kadm5_free_principal_ent(lhandle, &princ_ent);
278*0Sstevel@tonic-gate     (void) kadm5_free_policy_ent(lhandle, &policy_ent);
279*0Sstevel@tonic-gate     return(code);
280*0Sstevel@tonic-gate   }
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate   if (code == KADM5_PASS_Q_CLASS) {
283*0Sstevel@tonic-gate 			sprintf(msg_ret,
284*0Sstevel@tonic-gate 				string_text(CHPASS_UTIL_TOO_FEW_CLASSES),
285*0Sstevel@tonic-gate 	    policy_ent.pw_min_classes);
286*0Sstevel@tonic-gate     (void) kadm5_free_principal_ent(lhandle, &princ_ent);
287*0Sstevel@tonic-gate     (void) kadm5_free_policy_ent(lhandle, &policy_ent);
288*0Sstevel@tonic-gate     return(code);
289*0Sstevel@tonic-gate   }
290*0Sstevel@tonic-gate 
291*0Sstevel@tonic-gate   if (code == KADM5_PASS_TOOSOON) {
292*0Sstevel@tonic-gate     time_t until;
293*0Sstevel@tonic-gate     char *time_string, *ptr;
294*0Sstevel@tonic-gate 
295*0Sstevel@tonic-gate 			until = princ_ent.last_pwd_change +
296*0Sstevel@tonic-gate 				policy_ent.pw_min_life;
297*0Sstevel@tonic-gate 
298*0Sstevel@tonic-gate     time_string = ctime(&until);
299*0Sstevel@tonic-gate 			if (*(ptr = &time_string[strlen(time_string)-1]) ==
300*0Sstevel@tonic-gate 			    '\n')
301*0Sstevel@tonic-gate       *ptr = '\0';
302*0Sstevel@tonic-gate 
303*0Sstevel@tonic-gate 			sprintf(msg_ret,
304*0Sstevel@tonic-gate 				string_text(CHPASS_UTIL_PASSWORD_TOO_SOON),
305*0Sstevel@tonic-gate 	    time_string);
306*0Sstevel@tonic-gate     (void) kadm5_free_principal_ent(lhandle, &princ_ent);
307*0Sstevel@tonic-gate     (void) kadm5_free_policy_ent(lhandle, &policy_ent);
308*0Sstevel@tonic-gate     return(code);
309*0Sstevel@tonic-gate 		} else {
310*0Sstevel@tonic-gate   /* We should never get here, but just in case ... */
311*0Sstevel@tonic-gate   sprintf(buffer, "%s %s", error_message(code),
312*0Sstevel@tonic-gate 	  string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE));
313*0Sstevel@tonic-gate 			sprintf(msg_ret, "%s\n%s\n",
314*0Sstevel@tonic-gate 				string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED),
315*0Sstevel@tonic-gate 	  buffer);
316*0Sstevel@tonic-gate   (void) kadm5_free_principal_ent(lhandle, &princ_ent);
317*0Sstevel@tonic-gate   (void) kadm5_free_policy_ent(lhandle, &policy_ent);
318*0Sstevel@tonic-gate   return(code);
319*0Sstevel@tonic-gate 		}
320*0Sstevel@tonic-gate 	} else {
321*0Sstevel@tonic-gate 		sprintf(msg_ret, "%s\n%s\n",
322*0Sstevel@tonic-gate 			string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED),
323*0Sstevel@tonic-gate 			"Password protocol in krb5.conf is not supported\n");
324*0Sstevel@tonic-gate 		return (-1);
325*0Sstevel@tonic-gate 	}
326*0Sstevel@tonic-gate }
327*0Sstevel@tonic-gate 
328*0Sstevel@tonic-gate /*
329*0Sstevel@tonic-gate  * krb5_chpw_result_code_string
330*0Sstevel@tonic-gate  *
331*0Sstevel@tonic-gate  * convert the return code received from the password server
332*0Sstevel@tonic-gate  * to a human-readable string.
333*0Sstevel@tonic-gate  */
334*0Sstevel@tonic-gate const char *
335*0Sstevel@tonic-gate chpw_error_message(kadm5_ret_t result_code)
336*0Sstevel@tonic-gate {
337*0Sstevel@tonic-gate 	switch (result_code) {
338*0Sstevel@tonic-gate 	case KRB5_KPASSWD_MALFORMED:
339*0Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Malformed request error"));
340*0Sstevel@tonic-gate 	case KRB5_KPASSWD_HARDERROR:
341*0Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Server error"));
342*0Sstevel@tonic-gate 	case KRB5_KPASSWD_AUTHERROR:
343*0Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Authentication error"));
344*0Sstevel@tonic-gate 	case KRB5_KPASSWD_SOFTERROR:
345*0Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Password change rejected"));
346*0Sstevel@tonic-gate 	case KRB5_KPASSWD_ACCESSDENIED:
347*0Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN,
348*0Sstevel@tonic-gate 				"Not authorized to change password"));
349*0Sstevel@tonic-gate 	case KRB5_KPASSWD_BAD_VERSION:
350*0Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Protocol version unsupported"));
351*0Sstevel@tonic-gate 	case KRB5_KPASSWD_INITIAL_FLAG_NEEDED:
352*0Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN,
353*0Sstevel@tonic-gate 				"initial flag required in changepw request"));
354*0Sstevel@tonic-gate 	case KRB5_KPASSWD_POLICY_REJECT:
355*0Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "new password fails policy"));
356*0Sstevel@tonic-gate 	case KRB5_KPASSWD_BAD_PRINCIPAL:
357*0Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN,
358*0Sstevel@tonic-gate 		    "target principal does not exist for "
359*0Sstevel@tonic-gate 		    "changepw request"));
360*0Sstevel@tonic-gate 	case KRB5_KPASSWD_ETYPE_NOSUPP:
361*0Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN,
362*0Sstevel@tonic-gate 		    "changepw request key sequence has an "
363*0Sstevel@tonic-gate 		    "unsupported Etype"));
364*0Sstevel@tonic-gate 	default:
365*0Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Password change failed"));
366*0Sstevel@tonic-gate 	}
367*0Sstevel@tonic-gate }
368