1*10598SGlenn.Barry@Sun.COM /*
2*10598SGlenn.Barry@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3*10598SGlenn.Barry@Sun.COM * Use is subject to license terms.
4*10598SGlenn.Barry@Sun.COM */
51770Sgtb /*
61770Sgtb ** set password functions added by Paul W. Nelson, Thursby Software Systems, Inc.
71770Sgtb */
81770Sgtb #include <string.h>
91770Sgtb
101770Sgtb #include "k5-int.h"
117934SMark.Phalan@Sun.COM /* Solaris Kerberos */
127934SMark.Phalan@Sun.COM /* #include "krb5_err.h" */
131770Sgtb #include "auth_con.h"
141770Sgtb
151770Sgtb
161770Sgtb krb5_error_code
krb5int_mk_chpw_req(krb5_context context,krb5_auth_context auth_context,krb5_data * ap_req,char * passwd,krb5_data * packet)177934SMark.Phalan@Sun.COM krb5int_mk_chpw_req(
187934SMark.Phalan@Sun.COM krb5_context context,
197934SMark.Phalan@Sun.COM krb5_auth_context auth_context,
207934SMark.Phalan@Sun.COM krb5_data *ap_req,
217934SMark.Phalan@Sun.COM char *passwd,
227934SMark.Phalan@Sun.COM krb5_data *packet)
231770Sgtb {
241770Sgtb krb5_error_code ret = 0;
251770Sgtb krb5_data clearpw;
261770Sgtb krb5_data cipherpw;
271770Sgtb krb5_replay_data replay;
281770Sgtb char *ptr;
291770Sgtb
301770Sgtb cipherpw.data = NULL;
311770Sgtb
321770Sgtb if ((ret = krb5_auth_con_setflags(context, auth_context,
331770Sgtb KRB5_AUTH_CONTEXT_DO_SEQUENCE)))
341770Sgtb goto cleanup;
351770Sgtb
361770Sgtb clearpw.length = strlen(passwd);
371770Sgtb clearpw.data = passwd;
381770Sgtb
391770Sgtb if ((ret = krb5_mk_priv(context, auth_context,
401770Sgtb &clearpw, &cipherpw, &replay)))
411770Sgtb goto cleanup;
421770Sgtb
431770Sgtb packet->length = 6 + ap_req->length + cipherpw.length;
441770Sgtb packet->data = (char *) malloc(packet->length);
451770Sgtb if (packet->data == NULL)
467934SMark.Phalan@Sun.COM {
471770Sgtb ret = ENOMEM;
481770Sgtb goto cleanup;
497934SMark.Phalan@Sun.COM }
501770Sgtb ptr = packet->data;
511770Sgtb
521770Sgtb /* length */
531770Sgtb
547934SMark.Phalan@Sun.COM *ptr++ = (packet->length>> 8) & 0xff;
551770Sgtb *ptr++ = packet->length & 0xff;
561770Sgtb
571770Sgtb /* version == 0x0001 big-endian */
581770Sgtb
591770Sgtb *ptr++ = 0;
601770Sgtb *ptr++ = 1;
611770Sgtb
621770Sgtb /* ap_req length, big-endian */
631770Sgtb
641770Sgtb *ptr++ = (ap_req->length>>8) & 0xff;
651770Sgtb *ptr++ = ap_req->length & 0xff;
661770Sgtb
671770Sgtb /* ap-req data */
681770Sgtb
691770Sgtb memcpy(ptr, ap_req->data, ap_req->length);
701770Sgtb ptr += ap_req->length;
711770Sgtb
721770Sgtb /* krb-priv of password */
731770Sgtb
741770Sgtb memcpy(ptr, cipherpw.data, cipherpw.length);
751770Sgtb
761770Sgtb cleanup:
771770Sgtb if(cipherpw.data != NULL) /* allocated by krb5_mk_priv */
781770Sgtb free(cipherpw.data);
791770Sgtb
801770Sgtb return(ret);
811770Sgtb }
821770Sgtb
831770Sgtb krb5_error_code
krb5int_rd_chpw_rep(krb5_context context,krb5_auth_context auth_context,krb5_data * packet,int * result_code,krb5_data * result_data)841770Sgtb krb5int_rd_chpw_rep(krb5_context context, krb5_auth_context auth_context, krb5_data *packet, int *result_code, krb5_data *result_data)
851770Sgtb {
861770Sgtb char *ptr;
871770Sgtb int plen, vno;
881770Sgtb krb5_data ap_rep;
891770Sgtb krb5_ap_rep_enc_part *ap_rep_enc;
901770Sgtb krb5_error_code ret;
911770Sgtb krb5_data cipherresult;
921770Sgtb krb5_data clearresult;
937934SMark.Phalan@Sun.COM /* Solaris Kerberos */
947934SMark.Phalan@Sun.COM krb5_error *krberror = NULL;
951770Sgtb krb5_replay_data replay;
961770Sgtb krb5_keyblock *tmp;
971770Sgtb
981770Sgtb if (packet->length < 4)
991770Sgtb /* either this, or the server is printing bad messages,
1001770Sgtb or the caller passed in garbage */
1011770Sgtb return(KRB5KRB_AP_ERR_MODIFIED);
1021770Sgtb
1031770Sgtb ptr = packet->data;
1041770Sgtb
1051770Sgtb /* verify length */
1061770Sgtb
1071770Sgtb plen = (*ptr++ & 0xff);
1081770Sgtb plen = (plen<<8) | (*ptr++ & 0xff);
1091770Sgtb
1107934SMark.Phalan@Sun.COM if (plen != packet->length)
1117934SMark.Phalan@Sun.COM {
1127934SMark.Phalan@Sun.COM /*
1137934SMark.Phalan@Sun.COM * MS KDCs *may* send back a KRB_ERROR. Although
1147934SMark.Phalan@Sun.COM * not 100% correct via RFC3244, it's something
1157934SMark.Phalan@Sun.COM * we can workaround here.
1167934SMark.Phalan@Sun.COM */
1177934SMark.Phalan@Sun.COM if (krb5_is_krb_error(packet)) {
1187934SMark.Phalan@Sun.COM
1197934SMark.Phalan@Sun.COM if ((ret = krb5_rd_error(context, packet, &krberror)))
1207934SMark.Phalan@Sun.COM return(ret);
1217934SMark.Phalan@Sun.COM
1227934SMark.Phalan@Sun.COM if (krberror->e_data.data == NULL) {
1237934SMark.Phalan@Sun.COM ret = ERROR_TABLE_BASE_krb5 + (krb5_error_code) krberror->error;
1247934SMark.Phalan@Sun.COM krb5_free_error(context, krberror);
1257934SMark.Phalan@Sun.COM return (ret);
1267934SMark.Phalan@Sun.COM }
1277934SMark.Phalan@Sun.COM }
1287934SMark.Phalan@Sun.COM else
1297934SMark.Phalan@Sun.COM {
1307934SMark.Phalan@Sun.COM return(KRB5KRB_AP_ERR_MODIFIED);
1317934SMark.Phalan@Sun.COM }
1327934SMark.Phalan@Sun.COM }
1337934SMark.Phalan@Sun.COM
1347934SMark.Phalan@Sun.COM /* Solaris Kerberos */
1357934SMark.Phalan@Sun.COM if (krberror != NULL) {
1367934SMark.Phalan@Sun.COM krb5_free_error(context, krberror);
1377934SMark.Phalan@Sun.COM krberror = NULL;
1387934SMark.Phalan@Sun.COM }
1391770Sgtb
1401770Sgtb /* verify version number */
1411770Sgtb
1421770Sgtb vno = (*ptr++ & 0xff);
1431770Sgtb vno = (vno<<8) | (*ptr++ & 0xff);
1441770Sgtb
1451770Sgtb if (vno != 1)
1461770Sgtb return(KRB5KDC_ERR_BAD_PVNO);
1471770Sgtb
1481770Sgtb /* read, check ap-rep length */
1491770Sgtb
1501770Sgtb ap_rep.length = (*ptr++ & 0xff);
1511770Sgtb ap_rep.length = (ap_rep.length<<8) | (*ptr++ & 0xff);
1521770Sgtb
1531770Sgtb if (ptr + ap_rep.length >= packet->data + packet->length)
1541770Sgtb return(KRB5KRB_AP_ERR_MODIFIED);
1551770Sgtb
1561770Sgtb if (ap_rep.length) {
1571770Sgtb /* verify ap_rep */
1581770Sgtb ap_rep.data = ptr;
1591770Sgtb ptr += ap_rep.length;
1601770Sgtb
1611770Sgtb /*
1621770Sgtb * Save send_subkey to later smash recv_subkey.
1631770Sgtb */
1641770Sgtb ret = krb5_auth_con_getsendsubkey(context, auth_context, &tmp);
1651770Sgtb if (ret)
1661770Sgtb return ret;
1671770Sgtb
1681770Sgtb ret = krb5_rd_rep(context, auth_context, &ap_rep, &ap_rep_enc);
1691770Sgtb if (ret) {
1701770Sgtb krb5_free_keyblock(context, tmp);
1711770Sgtb return(ret);
1721770Sgtb }
1731770Sgtb
1741770Sgtb krb5_free_ap_rep_enc_part(context, ap_rep_enc);
1751770Sgtb
1761770Sgtb /* extract and decrypt the result */
1771770Sgtb
1781770Sgtb cipherresult.data = ptr;
1791770Sgtb cipherresult.length = (packet->data + packet->length) - ptr;
1801770Sgtb
1811770Sgtb /*
1821770Sgtb * Smash recv_subkey to be send_subkey, per spec.
1831770Sgtb */
1841770Sgtb ret = krb5_auth_con_setrecvsubkey(context, auth_context, tmp);
1851770Sgtb krb5_free_keyblock(context, tmp);
1861770Sgtb if (ret)
1871770Sgtb return ret;
1881770Sgtb
1891770Sgtb ret = krb5_rd_priv(context, auth_context, &cipherresult, &clearresult,
1901770Sgtb &replay);
1911770Sgtb
1921770Sgtb if (ret)
1931770Sgtb return(ret);
1941770Sgtb } else {
1951770Sgtb cipherresult.data = ptr;
1961770Sgtb cipherresult.length = (packet->data + packet->length) - ptr;
1971770Sgtb
1981770Sgtb if ((ret = krb5_rd_error(context, &cipherresult, &krberror)))
1991770Sgtb return(ret);
2001770Sgtb
2011770Sgtb clearresult = krberror->e_data;
2021770Sgtb }
2031770Sgtb
2041770Sgtb if (clearresult.length < 2) {
2051770Sgtb ret = KRB5KRB_AP_ERR_MODIFIED;
2061770Sgtb goto cleanup;
2071770Sgtb }
2081770Sgtb
2091770Sgtb ptr = clearresult.data;
2101770Sgtb
2111770Sgtb *result_code = (*ptr++ & 0xff);
2121770Sgtb *result_code = (*result_code<<8) | (*ptr++ & 0xff);
2131770Sgtb
2141770Sgtb if ((*result_code < KRB5_KPASSWD_SUCCESS) ||
2151770Sgtb (*result_code > KRB5_KPASSWD_INITIAL_FLAG_NEEDED)) {
2161770Sgtb ret = KRB5KRB_AP_ERR_MODIFIED;
2171770Sgtb goto cleanup;
2181770Sgtb }
2191770Sgtb
2201770Sgtb /* all success replies should be authenticated/encrypted */
2211770Sgtb
2221770Sgtb if ((ap_rep.length == 0) && (*result_code == KRB5_KPASSWD_SUCCESS)) {
2231770Sgtb ret = KRB5KRB_AP_ERR_MODIFIED;
2241770Sgtb goto cleanup;
2251770Sgtb }
2261770Sgtb
2271770Sgtb result_data->length = (clearresult.data + clearresult.length) - ptr;
2281770Sgtb
2291770Sgtb if (result_data->length) {
2301770Sgtb result_data->data = (char *) malloc(result_data->length);
2311770Sgtb if (result_data->data == NULL) {
2321770Sgtb ret = ENOMEM;
2331770Sgtb goto cleanup;
2341770Sgtb }
2351770Sgtb memcpy(result_data->data, ptr, result_data->length);
2361770Sgtb } else {
2371770Sgtb result_data->data = NULL;
2381770Sgtb }
2391770Sgtb
2401770Sgtb ret = 0;
2411770Sgtb
2421770Sgtb cleanup:
2431770Sgtb if (ap_rep.length) {
2441770Sgtb krb5_xfree(clearresult.data);
2451770Sgtb } else {
2461770Sgtb krb5_free_error(context, krberror);
2471770Sgtb }
2481770Sgtb
2491770Sgtb return(ret);
2501770Sgtb }
2511770Sgtb
2521770Sgtb krb5_error_code KRB5_CALLCONV
krb5_chpw_result_code_string(krb5_context context,int result_code,char ** code_string)2531770Sgtb krb5_chpw_result_code_string(krb5_context context, int result_code, char **code_string)
2541770Sgtb {
2551770Sgtb switch (result_code) {
2561770Sgtb case KRB5_KPASSWD_MALFORMED:
2571770Sgtb *code_string = "Malformed request error";
2581770Sgtb break;
2591770Sgtb case KRB5_KPASSWD_HARDERROR:
2601770Sgtb *code_string = "Server error";
2611770Sgtb break;
2621770Sgtb case KRB5_KPASSWD_AUTHERROR:
2631770Sgtb *code_string = "Authentication error";
2641770Sgtb break;
2651770Sgtb case KRB5_KPASSWD_SOFTERROR:
2661770Sgtb *code_string = "Password change rejected";
2671770Sgtb break;
2681770Sgtb default:
2691770Sgtb *code_string = "Password change failed";
2701770Sgtb break;
2711770Sgtb }
2721770Sgtb
2731770Sgtb return(0);
2741770Sgtb }
2751770Sgtb
2761770Sgtb krb5_error_code
krb5int_mk_setpw_req(krb5_context context,krb5_auth_context auth_context,krb5_data * ap_req,krb5_principal targprinc,char * passwd,krb5_data * packet)2771770Sgtb krb5int_mk_setpw_req(
2781770Sgtb krb5_context context,
2791770Sgtb krb5_auth_context auth_context,
2801770Sgtb krb5_data *ap_req,
2811770Sgtb krb5_principal targprinc,
2821770Sgtb char *passwd,
2831770Sgtb krb5_data *packet )
2841770Sgtb {
2851770Sgtb krb5_error_code ret;
2861770Sgtb krb5_data cipherpw;
2871770Sgtb krb5_data *encoded_setpw;
288*10598SGlenn.Barry@Sun.COM struct krb5_setpw_req req;
2891770Sgtb
2901770Sgtb char *ptr;
2911770Sgtb
292*10598SGlenn.Barry@Sun.COM cipherpw.data = NULL;
293*10598SGlenn.Barry@Sun.COM cipherpw.length = 0;
2941770Sgtb
2951770Sgtb if ((ret = krb5_auth_con_setflags(context, auth_context,
2961770Sgtb KRB5_AUTH_CONTEXT_DO_SEQUENCE)))
2971770Sgtb return(ret);
2981770Sgtb
299*10598SGlenn.Barry@Sun.COM req.target = targprinc;
300*10598SGlenn.Barry@Sun.COM req.password.data = passwd;
301*10598SGlenn.Barry@Sun.COM req.password.length = strlen(passwd);
302*10598SGlenn.Barry@Sun.COM ret = encode_krb5_setpw_req(&req, &encoded_setpw);
3031770Sgtb if (ret) {
3041770Sgtb return ret;
3051770Sgtb }
3061770Sgtb
3071770Sgtb if ( (ret = krb5_mk_priv(context, auth_context, encoded_setpw, &cipherpw, NULL)) != 0) {
3081770Sgtb krb5_free_data( context, encoded_setpw);
3091770Sgtb return(ret);
3101770Sgtb }
3111770Sgtb krb5_free_data( context, encoded_setpw);
3121770Sgtb
3131770Sgtb
3141770Sgtb packet->length = 6 + ap_req->length + cipherpw.length;
3151770Sgtb packet->data = (char *) malloc(packet->length);
3161770Sgtb if (packet->data == NULL) {
3171770Sgtb ret = ENOMEM;
3181770Sgtb goto cleanup;
3191770Sgtb }
3201770Sgtb ptr = packet->data;
3211770Sgtb /*
3221770Sgtb ** build the packet -
3231770Sgtb */
3241770Sgtb /* put in the length */
3251770Sgtb *ptr++ = (packet->length>>8) & 0xff;
3261770Sgtb *ptr++ = packet->length & 0xff;
3271770Sgtb /* put in the version */
3281770Sgtb *ptr++ = (char)0xff;
3291770Sgtb *ptr++ = (char)0x80;
3301770Sgtb /* the ap_req length is big endian */
3311770Sgtb *ptr++ = (ap_req->length>>8) & 0xff;
3321770Sgtb *ptr++ = ap_req->length & 0xff;
3331770Sgtb /* put in the request data */
3341770Sgtb memcpy(ptr, ap_req->data, ap_req->length);
3351770Sgtb ptr += ap_req->length;
3361770Sgtb /*
3371770Sgtb ** put in the "private" password data -
3381770Sgtb */
3391770Sgtb memcpy(ptr, cipherpw.data, cipherpw.length);
3401770Sgtb ret = 0;
3411770Sgtb cleanup:
3421770Sgtb if (cipherpw.data)
3431770Sgtb krb5_free_data_contents(context, &cipherpw);
3441770Sgtb if ((ret != 0) && packet->data) {
3451770Sgtb free( packet->data);
3461770Sgtb packet->data = NULL;
3471770Sgtb }
3481770Sgtb return ret;
3491770Sgtb }
3501770Sgtb
3511770Sgtb krb5_error_code
krb5int_rd_setpw_rep(krb5_context context,krb5_auth_context auth_context,krb5_data * packet,int * result_code,krb5_data * result_data)3521770Sgtb krb5int_rd_setpw_rep( krb5_context context, krb5_auth_context auth_context, krb5_data *packet,
3531770Sgtb int *result_code, krb5_data *result_data )
3541770Sgtb {
3551770Sgtb char *ptr;
3561770Sgtb unsigned int message_length, version_number;
3571770Sgtb krb5_data ap_rep;
3581770Sgtb krb5_ap_rep_enc_part *ap_rep_enc;
3591770Sgtb krb5_error_code ret;
3601770Sgtb krb5_data cipherresult;
3611770Sgtb krb5_data clearresult;
3621770Sgtb krb5_keyblock *tmpkey;
3631770Sgtb /*
3641770Sgtb ** validate the packet length -
3651770Sgtb */
3661770Sgtb if (packet->length < 4)
3671770Sgtb return(KRB5KRB_AP_ERR_MODIFIED);
3681770Sgtb
3691770Sgtb ptr = packet->data;
3701770Sgtb
3711770Sgtb /*
3721770Sgtb ** see if it is an error
3731770Sgtb */
3741770Sgtb if (krb5_is_krb_error(packet)) {
3751770Sgtb krb5_error *krberror;
3761770Sgtb if ((ret = krb5_rd_error(context, packet, &krberror)))
3771770Sgtb return(ret);
3781770Sgtb if (krberror->e_data.data == NULL) {
3791770Sgtb ret = ERROR_TABLE_BASE_krb5 + (krb5_error_code) krberror->error;
3801770Sgtb krb5_free_error(context, krberror);
3811770Sgtb return (ret);
3821770Sgtb }
3831770Sgtb clearresult = krberror->e_data;
3841770Sgtb krberror->e_data.data = NULL; /*So we can free it later*/
3851770Sgtb krberror->e_data.length = 0;
3861770Sgtb krb5_free_error(context, krberror);
3871770Sgtb
3881770Sgtb } else { /* Not an error*/
3891770Sgtb
3901770Sgtb /*
3911770Sgtb ** validate the message length -
3921770Sgtb ** length is big endian
3931770Sgtb */
3941770Sgtb message_length = (((ptr[0] << 8)&0xff) | (ptr[1]&0xff));
3951770Sgtb ptr += 2;
3961770Sgtb /*
3971770Sgtb ** make sure the message length and packet length agree -
3981770Sgtb */
3991770Sgtb if (message_length != packet->length)
4001770Sgtb return(KRB5KRB_AP_ERR_MODIFIED);
4011770Sgtb /*
4021770Sgtb ** get the version number -
4031770Sgtb */
4041770Sgtb version_number = (((ptr[0] << 8)&0xff) | (ptr[1]&0xff));
4051770Sgtb ptr += 2;
4061770Sgtb /*
4071770Sgtb ** make sure we support the version returned -
4081770Sgtb */
4091770Sgtb /*
4101770Sgtb ** set password version is 0xff80, change password version is 1
4111770Sgtb */
4127934SMark.Phalan@Sun.COM if (version_number != 1 && version_number != 0xff80)
4131770Sgtb return(KRB5KDC_ERR_BAD_PVNO);
4141770Sgtb /*
4151770Sgtb ** now fill in ap_rep with the reply -
4161770Sgtb */
4171770Sgtb /*
4181770Sgtb ** get the reply length -
4191770Sgtb */
4201770Sgtb ap_rep.length = (((ptr[0] << 8)&0xff) | (ptr[1]&0xff));
4211770Sgtb ptr += 2;
4221770Sgtb /*
4231770Sgtb ** validate ap_rep length agrees with the packet length -
4241770Sgtb */
4251770Sgtb if (ptr + ap_rep.length >= packet->data + packet->length)
4261770Sgtb return(KRB5KRB_AP_ERR_MODIFIED);
4271770Sgtb /*
4281770Sgtb ** if data was returned, set the ap_rep ptr -
4291770Sgtb */
4301770Sgtb if( ap_rep.length ) {
4311770Sgtb ap_rep.data = ptr;
4321770Sgtb ptr += ap_rep.length;
4331770Sgtb
4341770Sgtb /*
4351770Sgtb * Save send_subkey to later smash recv_subkey.
4361770Sgtb */
4371770Sgtb ret = krb5_auth_con_getsendsubkey(context, auth_context, &tmpkey);
4381770Sgtb if (ret)
4391770Sgtb return ret;
4401770Sgtb
4411770Sgtb ret = krb5_rd_rep(context, auth_context, &ap_rep, &ap_rep_enc);
4421770Sgtb if (ret) {
4431770Sgtb krb5_free_keyblock(context, tmpkey);
4441770Sgtb return(ret);
4451770Sgtb }
4461770Sgtb
4471770Sgtb krb5_free_ap_rep_enc_part(context, ap_rep_enc);
4481770Sgtb /*
4491770Sgtb ** now decrypt the result -
4501770Sgtb */
4511770Sgtb cipherresult.data = ptr;
4521770Sgtb cipherresult.length = (packet->data + packet->length) - ptr;
4531770Sgtb
4541770Sgtb /*
4551770Sgtb * Smash recv_subkey to be send_subkey, per spec.
4561770Sgtb */
4571770Sgtb ret = krb5_auth_con_setrecvsubkey(context, auth_context, tmpkey);
4581770Sgtb krb5_free_keyblock(context, tmpkey);
4591770Sgtb if (ret)
4601770Sgtb return ret;
4611770Sgtb
4621770Sgtb ret = krb5_rd_priv(context, auth_context, &cipherresult, &clearresult,
4631770Sgtb NULL);
4641770Sgtb if (ret)
4651770Sgtb return(ret);
4661770Sgtb } /*We got an ap_rep*/
4671770Sgtb else
4681770Sgtb return (KRB5KRB_AP_ERR_MODIFIED);
4691770Sgtb } /*Response instead of error*/
4701770Sgtb
4711770Sgtb /*
4721770Sgtb ** validate the cleartext length
4731770Sgtb */
4741770Sgtb if (clearresult.length < 2) {
4751770Sgtb ret = KRB5KRB_AP_ERR_MODIFIED;
4761770Sgtb goto cleanup;
4771770Sgtb }
4781770Sgtb /*
4791770Sgtb ** now decode the result -
4801770Sgtb */
4811770Sgtb ptr = clearresult.data;
4821770Sgtb
4831770Sgtb *result_code = (((ptr[0] << 8)&0xff) | (ptr[1]&0xff));
4841770Sgtb ptr += 2;
4851770Sgtb
4861770Sgtb /*
4871770Sgtb ** result code 5 is access denied
4881770Sgtb */
4891770Sgtb if ((*result_code < KRB5_KPASSWD_SUCCESS) || (*result_code > 5))
4901770Sgtb {
4911770Sgtb ret = KRB5KRB_AP_ERR_MODIFIED;
4921770Sgtb goto cleanup;
4931770Sgtb }
4941770Sgtb /*
4951770Sgtb ** all success replies should be authenticated/encrypted
4961770Sgtb */
4971770Sgtb if( (ap_rep.length == 0) && (*result_code == KRB5_KPASSWD_SUCCESS) )
4981770Sgtb {
4991770Sgtb ret = KRB5KRB_AP_ERR_MODIFIED;
5001770Sgtb goto cleanup;
5011770Sgtb }
5021770Sgtb
5031770Sgtb if (result_data) {
5041770Sgtb result_data->length = (clearresult.data + clearresult.length) - ptr;
5051770Sgtb
5061770Sgtb if (result_data->length)
5071770Sgtb {
5081770Sgtb result_data->data = (char *) malloc(result_data->length);
5091770Sgtb if (result_data->data)
5101770Sgtb memcpy(result_data->data, ptr, result_data->length);
5111770Sgtb }
5121770Sgtb else
5131770Sgtb result_data->data = NULL;
5141770Sgtb }
5151770Sgtb ret = 0;
5161770Sgtb
5171770Sgtb cleanup:
5181770Sgtb krb5_free_data_contents(context, &clearresult);
5191770Sgtb return(ret);
5201770Sgtb }
5211770Sgtb
5221770Sgtb krb5_error_code
krb5int_setpw_result_code_string(krb5_context context,int result_code,const char ** code_string)5231770Sgtb krb5int_setpw_result_code_string( krb5_context context, int result_code, const char **code_string )
5241770Sgtb {
5251770Sgtb switch (result_code)
5261770Sgtb {
5271770Sgtb case KRB5_KPASSWD_MALFORMED:
5281770Sgtb *code_string = "Malformed request error";
5291770Sgtb break;
5301770Sgtb case KRB5_KPASSWD_HARDERROR:
5311770Sgtb *code_string = "Server error";
5321770Sgtb break;
5331770Sgtb case KRB5_KPASSWD_AUTHERROR:
5341770Sgtb *code_string = "Authentication error";
5351770Sgtb break;
5361770Sgtb case KRB5_KPASSWD_SOFTERROR:
5371770Sgtb *code_string = "Password change rejected";
5381770Sgtb break;
5391770Sgtb case 5: /* access denied */
5401770Sgtb *code_string = "Access denied";
5411770Sgtb break;
5421770Sgtb case 6: /* bad version */
5431770Sgtb *code_string = "Wrong protocol version";
5441770Sgtb break;
5451770Sgtb case 7: /* initial flag is needed */
5461770Sgtb *code_string = "Initial password required";
5471770Sgtb break;
5481770Sgtb case 0:
5491770Sgtb *code_string = "Success";
5501770Sgtb default:
5511770Sgtb *code_string = "Password change failed";
5521770Sgtb break;
5531770Sgtb }
5541770Sgtb
5551770Sgtb return(0);
5561770Sgtb }
5571770Sgtb
558