summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README3
-rw-r--r--src/include/ChangeLog11
-rw-r--r--src/include/k5-int.h26
-rw-r--r--src/include/krb5.hin20
-rw-r--r--src/lib/ChangeLog4
-rw-r--r--src/lib/krb5/asn.1/ChangeLog4
-rw-r--r--src/lib/krb5/asn.1/krb5_encode.c17
-rw-r--r--src/lib/krb5/krb/ChangeLog17
-rw-r--r--src/lib/krb5/krb/chpw.c285
-rw-r--r--src/lib/krb5/os/ChangeLog13
-rw-r--r--src/lib/krb5/os/changepw.c115
-rw-r--r--src/lib/krb5_32.def2
12 files changed, 486 insertions, 31 deletions
diff --git a/README b/README
index 1a4ddfca93..83e706e624 100644
--- a/README
+++ b/README
@@ -538,6 +538,9 @@ providing patches for numerous buffer overruns.
Thanks to Christopher Thompson and Marcus Watts for discovering the
ftpd security bug.
+Thanks to Paul Nelson of Thursby Software Systems for implementing the
+Microsoft set password protocol.
+
Thanks to the members of the Kerberos V5 development team at MIT, both
past and present: Danilo Almeida, Jay Berkenbilt, Richard Basch, Mitch
Berger, John Carr, Don Davis, Alexandra Ellwood, Nancy Gilman, Matt
diff --git a/src/include/ChangeLog b/src/include/ChangeLog
index 85f8920243..53947082b0 100644
--- a/src/include/ChangeLog
+++ b/src/include/ChangeLog
@@ -1,3 +1,14 @@
+2003-04-17 Sam Hartman <hartmans@mit.edu>
+
+ * k5-int.h: Add encode_krb5_setpw_req
+
+2003-04-15 Sam Hartman <hartmans@mit.edu>
+
+ * krb5.hin: Add krb5_set_password
+ Move krb5*_chpw internals to k5int.h
+
+ * k5-int.h: Add prototypes for set-password helper functions
+
2003-04-24 Ken Raeburn <raeburn@mit.edu>
* Makefile.in ($(srcdir)/krb5/autoconf.stmp): Try running
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index 41c325da1e..ec7381bcf3 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -1270,6 +1270,9 @@ krb5_error_code encode_krb5_sam_response
krb5_error_code encode_krb5_predicted_sam_response
(const krb5_predicted_sam_response * , krb5_data **);
+krb5_error_code encode_krb5_setpw_req
+(const krb5_principal target, char *password, krb5_data **code);
+
/*************************************************************************
* End of prototypes for krb5_encode.c
*************************************************************************/
@@ -1559,6 +1562,29 @@ krb5_error_code KRB5_CALLCONV krb5_cc_retrieve_cred_default
void krb5int_set_prompt_types
(krb5_context, krb5_prompt_type *);
+/* set and change password helpers */
+
+krb5_error_code krb5int_mk_chpw_req
+ (krb5_context context, krb5_auth_context auth_context,
+ krb5_data *ap_req, char *passwd, krb5_data *packet);
+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);
+krb5_error_code KRB5_CALLCONV krb5_chpw_result_code_string
+ (krb5_context context, int result_code,
+ char **result_codestr);
+krb5_error_code krb5int_mk_setpw_req
+ (krb5_context context, krb5_auth_context auth_context,
+ krb5_data *ap_req, krb5_principal targetprinc, char *passwd, krb5_data *packet);
+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);
+krb5_error_code krb5int_setpw_result_code_string
+ (krb5_context context, int result_code,
+ const char **result_codestr);
+
#if defined(macintosh) && defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
diff --git a/src/include/krb5.hin b/src/include/krb5.hin
index eece828f1f..d43647dd4c 100644
--- a/src/include/krb5.hin
+++ b/src/include/krb5.hin
@@ -1658,18 +1658,6 @@ krb5_error_code KRB5_CALLCONV krb5_524_conv_principal
(krb5_context context, krb5_const_principal princ,
char *name, char *inst, char *realm);
-#if KRB5_PRIVATE
-krb5_error_code KRB5_CALLCONV krb5_mk_chpw_req
- (krb5_context context, krb5_auth_context auth_context,
- krb5_data *ap_req, char *passwd, krb5_data *packet);
-krb5_error_code KRB5_CALLCONV krb5_rd_chpw_rep
- (krb5_context context, krb5_auth_context auth_context,
- krb5_data *packet, int *result_code,
- krb5_data *result_data);
-krb5_error_code KRB5_CALLCONV krb5_chpw_result_code_string
- (krb5_context context, int result_code,
- char **result_codestr);
-#endif
/* libkt.spec */
#if KRB5_PRIVATE
@@ -1871,6 +1859,14 @@ krb5_change_password
(krb5_context context, krb5_creds *creds, char *newpw,
int *result_code, krb5_data *result_code_string,
krb5_data *result_string);
+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);
+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);
#if KRB5_PRIVATE
#ifndef macintosh
diff --git a/src/lib/ChangeLog b/src/lib/ChangeLog
index bfa7678b0c..fb87043923 100644
--- a/src/lib/ChangeLog
+++ b/src/lib/ChangeLog
@@ -1,3 +1,7 @@
+2003-04-15 Sam Hartman <hartmans@mit.edu>
+
+ * krb5_32.def: Add krb5_set_password and krb5_set_password_using_ccache
+
2003-02-10 Tom Yu <tlyu@mit.edu>
* Makefile.in (K4LIBS): Revert previous.
diff --git a/src/lib/krb5/asn.1/ChangeLog b/src/lib/krb5/asn.1/ChangeLog
index 01e6d96cde..4eaa5fe61a 100644
--- a/src/lib/krb5/asn.1/ChangeLog
+++ b/src/lib/krb5/asn.1/ChangeLog
@@ -1,3 +1,7 @@
+2003-04-15 Sam Hartman <hartmans@mit.edu>
+
+ * krb5_encode.c (encode_krb5_setpw_req): new function
+
2003-04-13 Ezra Peisach <epeisach@mit.edu>
* asn1_k_decode.c (asn1_decode_kdc_req_body): Fix memory leak if
diff --git a/src/lib/krb5/asn.1/krb5_encode.c b/src/lib/krb5/asn.1/krb5_encode.c
index 2a4f7bb140..04deef0d24 100644
--- a/src/lib/krb5/asn.1/krb5_encode.c
+++ b/src/lib/krb5/asn.1/krb5_encode.c
@@ -822,3 +822,20 @@ krb5_error_code encode_krb5_predicted_sam_response(const krb5_predicted_sam_resp
sum += length;
krb5_cleanup();
}
+
+krb5_error_code encode_krb5_setpw_req(const krb5_principal target,
+ char *password, krb5_data **code)
+{
+ /* Macros really want us to have a variable called rep which we do not need*/
+ const char *rep = "dummy string";
+
+ krb5_setup();
+
+ krb5_addfield(target,2,asn1_encode_realm);
+ krb5_addfield(target,1,asn1_encode_principal_name);
+ krb5_addlenfield(strlen(password), password,0,asn1_encode_octetstring);
+ krb5_makeseq();
+
+
+ krb5_cleanup();
+}
diff --git a/src/lib/krb5/krb/ChangeLog b/src/lib/krb5/krb/ChangeLog
index 2dfe463973..a560a9640b 100644
--- a/src/lib/krb5/krb/ChangeLog
+++ b/src/lib/krb5/krb/ChangeLog
@@ -1,3 +1,19 @@
+2003-04-25 Sam Hartman <hartmans@mit.edu>
+
+ * chpw.c (krb5int_rd_setpw_rep): Fix error handling; allow
+ krberrors to be read correctly; fix memory alloctaion so that
+ allocated structures are freed.
+
+2003-04-16 Sam Hartman <hartmans@mit.edu>
+
+ * chpw.c (krb5int_mk_setpw_req): Use encode_krb5_setpw_req. Fix
+ memory handling to free data that is allocated
+
+2003-04-15 Sam Hartman <hartmans@mit.edu>
+
+ * chpw.c (krb5int_mk_setpw_req krb5int_rd_setpw_rep): New function
+
+=======
2003-04-24 Ezra Peisach <epeisach@mit.edu>
* kfree.c (krb5_free_pwd_sequences): Correction to previous
@@ -8,6 +24,7 @@
* kfree.c (krb5_free_pwd_sequences): Actually free the entire
sequence of passwd_phase_elements and not just the first one.
+>>>>>>> 5.385
2003-04-13 Ken Raeburn <raeburn@mit.edu>
* init_ctx.c (DEFAULT_ETYPE_LIST): Add AES with 256 bits at the
diff --git a/src/lib/krb5/krb/chpw.c b/src/lib/krb5/krb/chpw.c
index bb2cfe9c7d..9c5a4078af 100644
--- a/src/lib/krb5/krb/chpw.c
+++ b/src/lib/krb5/krb/chpw.c
@@ -1,11 +1,15 @@
+/*
+** set password functions added by Paul W. Nelson, Thursby Software Systems, Inc.
+*/
#include <string.h>
#include "k5-int.h"
#include "krb5_err.h"
#include "auth_con.h"
-krb5_error_code KRB5_CALLCONV
-krb5_mk_chpw_req(krb5_context context, krb5_auth_context auth_context, krb5_data *ap_req, char *passwd, krb5_data *packet)
+
+krb5_error_code
+krb5int_mk_chpw_req(krb5_context context, krb5_auth_context auth_context, krb5_data *ap_req, char *passwd, krb5_data *packet)
{
krb5_error_code ret = 0;
krb5_data clearpw;
@@ -66,8 +70,8 @@ cleanup:
return(ret);
}
-krb5_error_code KRB5_CALLCONV
-krb5_rd_chpw_rep(krb5_context context, krb5_auth_context auth_context, krb5_data *packet, int *result_code, krb5_data *result_data)
+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)
{
char *ptr;
int plen, vno;
@@ -221,3 +225,276 @@ krb5_chpw_result_code_string(krb5_context context, int result_code, char **code_
return(0);
}
+
+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 )
+{
+ krb5_error_code ret;
+ krb5_data cipherpw;
+ krb5_data *encoded_setpw;
+
+ char *ptr;
+ int count = 2;
+
+ cipherpw.data = NULL;
+ cipherpw.length = 0;
+
+ if (ret = krb5_auth_con_setflags(context, auth_context,
+ KRB5_AUTH_CONTEXT_DO_SEQUENCE))
+ return(ret);
+
+ ret = encode_krb5_setpw_req(targprinc, passwd, &encoded_setpw);
+ if (ret) {
+ return ret;
+ }
+
+ if ( (ret = krb5_mk_priv(context, auth_context, encoded_setpw, &cipherpw, NULL)) != 0) {
+ krb5_free_data( context, encoded_setpw);
+ return(ret);
+ }
+ krb5_free_data( context, encoded_setpw);
+
+
+ packet->length = 6 + ap_req->length + cipherpw.length;
+ packet->data = (char *) malloc(packet->length);
+ if (packet->data == NULL) {
+ ret = ENOMEM;
+ goto cleanup;
+ }
+ ptr = packet->data;
+/*
+** build the packet -
+*/
+/* put in the length */
+ *ptr++ = (packet->length>>8) & 0xff;
+ *ptr++ = packet->length & 0xff;
+/* put in the version */
+ *ptr++ = (char)0xff;
+ *ptr++ = (char)0x80;
+/* the ap_req length is big endian */
+ *ptr++ = (ap_req->length>>8) & 0xff;
+ *ptr++ = ap_req->length & 0xff;
+/* put in the request data */
+ memcpy(ptr, ap_req->data, ap_req->length);
+ ptr += ap_req->length;
+/*
+** put in the "private" password data -
+*/
+ memcpy(ptr, cipherpw.data, cipherpw.length);
+ ret = 0;
+ cleanup:
+ if (cipherpw.data)
+ krb5_free_data_contents(context, &cipherpw);
+ if ((ret != 0) && packet->data) {
+ free( packet->data);
+ packet->data = NULL;
+ }
+ return ret;
+}
+
+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 )
+{
+ char *ptr;
+ unsigned int message_length, version_number;
+ krb5_data ap_rep;
+ krb5_ap_rep_enc_part *ap_rep_enc;
+ krb5_error_code ret;
+ krb5_data cipherresult;
+ krb5_data clearresult;
+ krb5_replay_data replay;
+/*
+** validate the packet length -
+*/
+ if (packet->length < 4)
+ return(KRB5KRB_AP_ERR_MODIFIED);
+
+ ptr = packet->data;
+
+/*
+** see if it is an error
+*/
+ if (krb5_is_krb_error(packet)) {
+ krb5_error *krberror;
+ if (ret = krb5_rd_error(context, packet, &krberror))
+ return(ret);
+ if (krberror->e_data.data == NULL) {
+ ret = ERROR_TABLE_BASE_krb5 + krberror->error;
+ krb5_free_error(context, krberror);
+ return (ret);
+ }
+ clearresult = krberror->e_data;
+ krberror->e_data.data = NULL; /*So we can free it later*/
+ krberror->e_data.length = 0;
+ krb5_free_error(context, krberror);
+
+ } else { /* Not an error*/
+
+/*
+** validate the message length -
+** length is big endian
+*/
+ message_length = (((ptr[0] << 8)&0xff) | (ptr[1]&0xff));
+ ptr += 2;
+/*
+** make sure the message length and packet length agree -
+*/
+ if (message_length != packet->length)
+ return(KRB5KRB_AP_ERR_MODIFIED);
+/*
+** get the version number -
+*/
+ version_number = (((ptr[0] << 8)&0xff) | (ptr[1]&0xff));
+ ptr += 2;
+/*
+** make sure we support the version returned -
+*/
+/*
+** set password version is 0xff80, change password version is 1
+*/
+ if (version_number != 0xff80 && version_number != 1)
+ return(KRB5KDC_ERR_BAD_PVNO);
+/*
+** now fill in ap_rep with the reply -
+*/
+/*
+** get the reply length -
+*/
+ ap_rep.length = (((ptr[0] << 8)&0xff) | (ptr[1]&0xff));
+ ptr += 2;
+/*
+** validate ap_rep length agrees with the packet length -
+*/
+ if (ptr + ap_rep.length >= packet->data + packet->length)
+ return(KRB5KRB_AP_ERR_MODIFIED);
+/*
+** if data was returned, set the ap_rep ptr -
+*/
+ if( ap_rep.length ) {
+ ap_rep.data = ptr;
+ ptr += ap_rep.length;
+
+ if (ret = krb5_rd_rep(context, auth_context, &ap_rep, &ap_rep_enc))
+ return(ret);
+
+ krb5_free_ap_rep_enc_part(context, ap_rep_enc);
+/*
+** now decrypt the result -
+*/
+ cipherresult.data = ptr;
+ cipherresult.length = (packet->data + packet->length) - ptr;
+
+ {
+ krb5_keyblock *saved_remote_subkey;
+/*
+** save the remote_subkey, so it doesn't get used when decoding
+*/
+ saved_remote_subkey = auth_context->remote_subkey;
+ auth_context->remote_subkey = NULL;
+
+ ret = krb5_rd_priv(context, auth_context, &cipherresult, &clearresult,
+ NULL);
+ auth_context->remote_subkey = saved_remote_subkey;
+ }
+
+ if (ret)
+ return(ret);
+ } /*We got an ap_rep*/
+ else
+ return (KRB5KRB_AP_ERR_MODIFIED);
+ } /*Response instead of error*/
+
+/*
+** validate the cleartext length
+*/
+ if (clearresult.length < 2) {
+ ret = KRB5KRB_AP_ERR_MODIFIED;
+ goto cleanup;
+ }
+/*
+** now decode the result -
+*/
+ ptr = clearresult.data;
+
+ *result_code = (((ptr[0] << 8)&0xff) | (ptr[1]&0xff));
+ ptr += 2;
+
+/*
+** result code 5 is access denied
+*/
+ if ((*result_code < KRB5_KPASSWD_SUCCESS) || (*result_code > 5))
+ {
+ ret = KRB5KRB_AP_ERR_MODIFIED;
+ goto cleanup;
+ }
+/*
+** all success replies should be authenticated/encrypted
+*/
+ if( (ap_rep.length == 0) && (*result_code == KRB5_KPASSWD_SUCCESS) )
+ {
+ ret = KRB5KRB_AP_ERR_MODIFIED;
+ goto cleanup;
+ }
+
+ if (result_data) {
+ result_data->length = (clearresult.data + clearresult.length) - ptr;
+
+ if (result_data->length)
+ {
+ result_data->data = (char *) malloc(result_data->length);
+ if (result_data->data)
+ memcpy(result_data->data, ptr, result_data->length);
+ }
+ else
+ result_data->data = NULL;
+ }
+ ret = 0;
+
+ cleanup:
+ krb5_free_data_contents(context, &clearresult);
+ return(ret);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_setpw_result_code_string( krb5_context context, int result_code, const char **code_string )
+{
+ switch (result_code)
+ {
+ case KRB5_KPASSWD_MALFORMED:
+ *code_string = "Malformed request error";
+ break;
+ case KRB5_KPASSWD_HARDERROR:
+ *code_string = "Server error";
+ break;
+ case KRB5_KPASSWD_AUTHERROR:
+ *code_string = "Authentication error";
+ break;
+ case KRB5_KPASSWD_SOFTERROR:
+ *code_string = "Password change rejected";
+ break;
+ case 5: /* access denied */
+ *code_string = "Access denied";
+ break;
+ case 6: /* bad version */
+ *code_string = "Wrong protocol version";
+ break;
+ case 7: /* initial flag is needed */
+ *code_string = "Initial password required";
+ break;
+ case 0:
+ *code_string = "Success";
+ default:
+ *code_string = "Password change failed";
+ break;
+ }
+
+ return(0);
+}
+
diff --git a/src/lib/krb5/os/ChangeLog b/src/lib/krb5/os/ChangeLog
index f3406c5b03..112629b1cf 100644
--- a/src/lib/krb5/os/ChangeLog
+++ b/src/lib/krb5/os/ChangeLog
@@ -1,3 +1,16 @@
+2003-04-24 Sam Hartman <hartmans@mit.edu>
+
+ * changepw.c (krb5_change_set_password): return error from
+ auth_con_setaddrs not last socket errno if auth_con_setaddrs fails
+
+2003-04-15 Sam Hartman <hartmans@mit.edu>
+
+ * changepw.c (krb5_change_set_password): Patches from Paul Nelson
+ to implement Microsoft set password protocol
+ (krb5_set_password_using_ccache): Use kadmin/changepw in target realm, not local realm and use a two-component principal
+ (krb5_change_set_password): Find the kpasswd server for the realm
+ of the target principal not the client
+
2003-04-13 Ken Raeburn <raeburn@mit.edu>
* read_pwd.c (krb5_read_password): Always free temporary storage
diff --git a/src/lib/krb5/os/changepw.c b/src/lib/krb5/os/changepw.c
index 60cb3a9158..a4f5422f39 100644
--- a/src/lib/krb5/os/changepw.c
+++ b/src/lib/krb5/os/changepw.c
@@ -24,6 +24,10 @@
* or implied warranty.
*
*/
+/*
+ * krb5_set_password - Implements set password per RFC 3244
+ * Added by Paul W. Nelson, Thursby Software Systems, Inc.
+ */
#define NEED_SOCKETS
#include "fake-addrinfo.h"
@@ -69,8 +73,16 @@ krb5_locate_kpasswd(krb5_context context, const krb5_data *realm,
}
+/*
+** The logic for setting and changing a password is mostly the same
+** krb5_change_set_password handles both cases
+** if set_password_for is NULL, then a password change is performed,
+** otherwise, the password is set for the principal indicated in set_password_for
+*/
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)
+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)
{
krb5_auth_context auth_context;
krb5_data ap_req, chpw_req, chpw_rep;
@@ -104,7 +116,7 @@ krb5_change_password(krb5_context context, krb5_creds *creds, char *newpw, int *
goto cleanup;
if ((code = krb5_locate_kpasswd(context,
- krb5_princ_realm(context, creds->client),
+ krb5_princ_realm(context, set_password_for),
&al)))
goto cleanup;
@@ -218,14 +230,15 @@ krb5_change_password(krb5_context context, krb5_creds *creds, char *newpw, int *
if ((code = krb5_auth_con_setaddrs(context, auth_context,
&local_kaddr, NULL))) {
- code = SOCKET_ERRNO;
- goto cleanup;
+ goto cleanup;
}
- if ((code = krb5_mk_chpw_req(context, auth_context, &ap_req,
- newpw, &chpw_req)))
+ if( set_password_for )
+ code = krb5int_mk_setpw_req(context, auth_context, &ap_req, set_password_for, newpw, &chpw_req);
+ else
+ code = krb5int_mk_chpw_req(context, auth_context, &ap_req, newpw, &chpw_req);
+ if (code)
{
- code = SOCKET_ERRNO;
goto cleanup;
}
@@ -289,19 +302,23 @@ krb5_change_password(krb5_context context, krb5_creds *creds, char *newpw, int *
NULL, &remote_kaddr)))
goto cleanup;
- if ((code = krb5_rd_chpw_rep(context, auth_context, &chpw_rep,
- &local_result_code,
- result_string)))
- goto cleanup;
+ if( set_password_for )
+ code = krb5int_rd_setpw_rep(context, auth_context, &chpw_rep, &local_result_code, result_string);
+ else
+ code = krb5int_rd_chpw_rep(context, auth_context, &chpw_rep, &local_result_code, result_string);
+ if (code)
+ goto cleanup;
if (result_code)
*result_code = local_result_code;
if (result_code_string) {
- if ((code = krb5_chpw_result_code_string(context,
- local_result_code,
- &code_string)))
- goto cleanup;
+ if( set_password_for )
+ code = krb5_setpw_result_code_string(context, local_result_code, (const char **)&code_string);
+ else
+ code = krb5_chpw_result_code_string(context, local_result_code, &code_string);
+ if(code)
+ goto cleanup;
result_code_string->length = strlen(code_string);
result_code_string->data = malloc(result_code_string->length);
@@ -343,3 +360,71 @@ cleanup:
return(code);
}
+
+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)
+{
+ return krb5_change_set_password(
+ context, creds, newpw, NULL, result_code, result_code_string, result_string );
+}
+
+/*
+ * krb5_set_password - Implements set password per RFC 3244
+ *
+ */
+
+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
+ )
+{
+ return krb5_change_set_password(
+ context, creds, newpw, change_password_for, result_code, result_code_string, result_string );
+}
+
+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
+ )
+{
+ krb5_creds creds;
+ krb5_creds *credsp;
+ krb5_error_code code;
+
+/*
+** get the proper creds for use with krb5_set_password -
+*/
+ memset( &creds, 0, sizeof(creds) );
+/*
+** first get the principal for the password service -
+*/
+ code = krb5_cc_get_principal( context, ccache, &creds.client );
+ if( !code )
+ {
+ code = krb5_build_principal( context, &creds.server,
+ krb5_princ_realm(context, change_password_for)->length,
+ krb5_princ_realm(context, change_password_for)->data,
+ "kadmin", "changepw", NULL );
+ if(!code)
+ {
+ code = krb5_get_credentials(context, 0, ccache, &creds, &credsp);
+ if( ! code )
+ {
+ code = krb5_set_password(context, credsp, newpw, change_password_for,
+ result_code, result_code_string,
+ result_string);
+ krb5_free_creds(context, credsp);
+ }
+ }
+ krb5_free_cred_contents(context, &creds);
+ }
+ return code;
+}
diff --git a/src/lib/krb5_32.def b/src/lib/krb5_32.def
index 53172a85c3..0d4d5f24d1 100644
--- a/src/lib/krb5_32.def
+++ b/src/lib/krb5_32.def
@@ -204,6 +204,8 @@ EXPORTS
krb5_sendauth
krb5_set_default_realm
krb5_set_default_tgs_enctypes
+krb5_set_password
+krb5_set_password_using_ccache
krb5_set_principal_realm
krb5_sname_to_principal
krb5_string_to_cksumtype