aboutsummaryrefslogtreecommitdiff
path: root/src/clients/kpasswd
diff options
context:
space:
mode:
authorSam Hartman <hartmans@mit.edu>2003-04-25 18:50:04 +0000
committerSam Hartman <hartmans@mit.edu>2003-04-25 18:50:04 +0000
commitec50322c3076ab4517fb4fb5cc3a931f6adb4f20 (patch)
treed6819f6614b1530875d5d9b6ccc2ca64afe6e69f /src/clients/kpasswd
parentdffb4a9da42dec49abe7ebae9501814ed493cf23 (diff)
downloadkrb5-ec50322c3076ab4517fb4fb5cc3a931f6adb4f20.zip
krb5-ec50322c3076ab4517fb4fb5cc3a931f6adb4f20.tar.gz
krb5-ec50322c3076ab4517fb4fb5cc3a931f6adb4f20.tar.bz2
Build ksetpw, a client for the Microsoft set password protocol. Not
of release quality yet, so don't actually install. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@15374 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/clients/kpasswd')
-rw-r--r--src/clients/kpasswd/ChangeLog6
-rw-r--r--src/clients/kpasswd/Makefile.in8
-rw-r--r--src/clients/kpasswd/ksetpwd.c312
3 files changed, 324 insertions, 2 deletions
diff --git a/src/clients/kpasswd/ChangeLog b/src/clients/kpasswd/ChangeLog
index 1019de4..ac31dda 100644
--- a/src/clients/kpasswd/ChangeLog
+++ b/src/clients/kpasswd/ChangeLog
@@ -1,3 +1,9 @@
+2003-04-25 Sam Hartman <hartmans@mit.edu>
+
+ * Makefile.in : Add rule to build ksetpw, a set/change password
+ client for the Microsoft protocol. We do not install this program
+ by default because it is not of release quality yet.
+
2003-02-25 Tom Yu <tlyu@mit.edu>
* kpasswd.c (main): Don't pass a NULL pointer to printf().
diff --git a/src/clients/kpasswd/Makefile.in b/src/clients/kpasswd/Makefile.in
index 89c1340..3f63943 100644
--- a/src/clients/kpasswd/Makefile.in
+++ b/src/clients/kpasswd/Makefile.in
@@ -8,12 +8,16 @@ PROG_RPATH=$(KRB5_LIBDIR)
kpasswd: kpasswd.o $(KRB5_BASE_DEPLIBS)
$(CC_LINK) -o kpasswd kpasswd.o $(KRB5_BASE_LIBS)
+ksetpwd: ksetpwd.o $(KRB5_BASE_DEPLIBS)
+ $(CC_LINK) -o ksetpwd ksetpwd.o $(KRB5_BASE_LIBS)
+
kpasswd.o: $(srcdir)/kpasswd.c
+ksetpwd.o: $(srcdir)/ksetpwd.c
-all-unix:: kpasswd
+all-unix:: kpasswd ksetpwd
clean-unix::
- $(RM) kpasswd.o kpasswd
+ $(RM) kpasswd.o kpasswd ksetpwd.o ksetpwd
install-all install-kdc install-server install-client install-unix::
$(INSTALL_PROGRAM) kpasswd $(DESTDIR)$(CLIENT_BINDIR)/`echo kpasswd|sed '$(transform)'`
diff --git a/src/clients/kpasswd/ksetpwd.c b/src/clients/kpasswd/ksetpwd.c
new file mode 100644
index 0000000..7b72b36
--- /dev/null
+++ b/src/clients/kpasswd/ksetpwd.c
@@ -0,0 +1,312 @@
+#include <krb5.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define TKTTIMELEFT 60*10 /* ten minutes */
+
+int verify_creds()
+{
+ krb5_context kcontext;
+ krb5_ccache ccache;
+ krb5_error_code kres;
+
+ kres = krb5_init_context(&kcontext);
+ if( kres == 0 )
+ {
+ kres = krb5_cc_default( kcontext, &ccache );
+ if( kres == 0 )
+ {
+ krb5_principal user_princ;
+
+ kres = krb5_cc_get_principal( kcontext, ccache, &user_princ );
+ if( kres == 0 )
+ krb5_free_principal( kcontext, user_princ );
+ krb5_cc_close( kcontext, ccache );
+ }
+ krb5_free_context(kcontext);
+ }
+ return kres;
+}
+
+void get_init_creds_opt_init( krb5_get_init_creds_opt *outOptions )
+{
+ krb5_preauthtype preauth[] = { KRB5_PADATA_ENC_TIMESTAMP };
+ krb5_enctype etypes[] = {ENCTYPE_DES_CBC_MD5, ENCTYPE_DES_CBC_CRC};
+ memset( outOptions, 0, sizeof(*outOptions) );
+ krb5_get_init_creds_opt_init(outOptions);
+ krb5_get_init_creds_opt_set_address_list(outOptions, NULL);
+ krb5_get_init_creds_opt_set_etype_list( outOptions, etypes, sizeof(etypes)/sizeof(krb5_enctype) );
+ krb5_get_init_creds_opt_set_preauth_list(outOptions, preauth, sizeof(preauth)/sizeof(krb5_preauthtype) );
+}
+
+typedef void * kbrccache_t;
+#define CCACHE_PREFIX_DEFAULT "MEMORY:C_"
+
+kbrccache_t userinitcontext(
+ const char * user, const char * domain, const char * passwd, const char * cachename, int initialize,
+ int * outError )
+{
+ krb5_context kcontext = 0;
+ krb5_ccache kcache = 0;
+ krb5_creds kcreds;
+ krb5_principal kme = 0;
+ krb5_error_code kres;
+ char * pPass = strdup( passwd );
+ char * pName = NULL;
+ char * pCacheName = NULL;
+ int numCreds = 0;
+
+ memset( &kcreds, 0, sizeof(kcreds) );
+ kres = krb5_init_context( &kcontext );
+ if( kres )
+ goto return_error;
+ if( domain )
+ kres = krb5_build_principal( kcontext, &kme, strlen(domain), domain, user, 0 );
+ else
+ kres = krb5_parse_name( kcontext, user, &kme );
+ if( kres )
+ goto fail;
+ krb5_unparse_name( kcontext, kme, &pName );
+ if( cachename )
+ {
+ pCacheName = malloc( strlen( pName ) + strlen( cachename ) + 1 );
+ if( pCacheName == NULL )
+ {
+ kres = KRB5_CC_NOMEM;
+ goto fail;
+ }
+ strcpy( pCacheName, cachename );
+ strcat( pCacheName, pName );
+ kres = krb5_cc_resolve( kcontext, pCacheName, &kcache );
+ if( kres )
+ {
+ kres = krb5_cc_resolve( kcontext, CCACHE_PREFIX_DEFAULT, &kcache );
+ if( kres == 0 )
+ pCacheName = strdup(CCACHE_PREFIX_DEFAULT);
+ }
+ }
+ else
+ {
+ kres = krb5_cc_default( kcontext, &kcache );
+ pCacheName = strdup( krb5_cc_get_name( kcontext, kcache ) );
+ }
+ if( kres )
+ {
+ krb5_free_context(kcontext);
+ goto return_error;
+ }
+ if( initialize )
+ krb5_cc_initialize( kcontext, kcache, kme );
+ if( kres == 0 && user && passwd )
+ {
+ long timeneeded = time(0L) +TKTTIMELEFT;
+ int have_credentials = 0;
+ krb5_cc_cursor cc_curs = NULL;
+ numCreds = 0;
+ if( (kres=krb5_cc_start_seq_get(kcontext, kcache, &cc_curs)) >= 0 )
+ {
+ while( (kres=krb5_cc_next_cred(kcontext, kcache, &cc_curs, &kcreds))== 0)
+ {
+ numCreds++;
+ if( krb5_principal_compare( kcontext, kme, kcreds.client ) )
+ {
+ if( kcreds.ticket_flags & TKT_FLG_INITIAL && kcreds.times.endtime>timeneeded )
+ have_credentials = 1;
+ }
+ krb5_free_cred_contents( kcontext, &kcreds );
+ if( have_credentials )
+ break;
+ }
+ krb5_cc_end_seq_get( kcontext, kcache, &cc_curs );
+ }
+ else
+ {
+ const char * errmsg = error_message(kres);
+ fprintf( stderr, "%s user init(%s): %s\n", "setpass", pName, errmsg );
+ }
+ if( kres != 0 || have_credentials == 0 )
+ {
+ krb5_get_init_creds_opt options;
+ get_init_creds_opt_init(&options);
+/*
+** no valid credentials - get new ones
+*/
+ kres = krb5_get_init_creds_password( kcontext, &kcreds, kme, pPass,
+ NULL /*prompter*/,
+ NULL /*data*/,
+ 0 /*starttime*/,
+ 0 /*in_tkt_service*/,
+ &options /*options*/ );
+ if( kres == 0 )
+ {
+ if( numCreds <= 0 )
+ kres = krb5_cc_initialize( kcontext, kcache, kme );
+ if( kres == 0 )
+ kres = krb5_cc_store_cred( kcontext, kcache, &kcreds );
+ if( kres == 0 )
+ have_credentials = 1;
+ }
+ }
+#ifdef NOTUSED
+ if( have_credentials )
+ {
+ int mstat;
+ kres = gss_krb5_ccache_name( &mstat, pCacheName, NULL );
+ if( getenv( ENV_DEBUG_LDAPKERB ) )
+ fprintf( stderr, "gss credentials cache set to %s(%d)\n", pCacheName, kres );
+ }
+#endif
+ krb5_cc_close( kcontext, kcache );
+ }
+fail:
+ if( kres )
+ {
+ const char * errmsg = error_message(kres);
+ fprintf( stderr, "%s user init(%s): %s\n", "setpass", pName, errmsg );
+ }
+ krb5_free_principal( kcontext, kme );
+ krb5_free_cred_contents( kcontext, &kcreds );
+ if( pName )
+ free( pName );
+ free(pPass);
+ krb5_free_context(kcontext);
+
+return_error:
+ if( kres )
+ {
+ if( pCacheName )
+ {
+ free(pCacheName);
+ pCacheName = NULL;
+ }
+ }
+ if( outError )
+ *outError = kres;
+ return pCacheName;
+}
+
+int init_creds()
+{
+ char user[512];
+ char * password = NULL;
+ int result;
+
+ user[0] = 0;
+ result = -1;
+
+ for(;;)
+ {
+ while( user[0] == 0 )
+ {
+ int userlen;
+ printf( "Username: ");
+ fflush(stdout);
+ if( fgets( user, sizeof(user), stdin ) == NULL )
+ return -1;
+ userlen = strlen( user);
+ if( userlen < 2 )
+ continue;
+ user[userlen-1] = 0; // get rid of the newline
+ break;
+ }
+ {
+ kbrccache_t usercontext;
+ password = getpass( "Password: ");
+ if( ! password )
+ return -1;
+ result = 0;
+ usercontext = userinitcontext( user, NULL, password, NULL, 1, &result );
+ if( usercontext )
+ break;
+ }
+ }
+ return result;
+}
+
+int main( int argc, char ** argv )
+{
+ char * new_password = NULL;
+ char * new_password2;
+ krb5_context kcontext;
+ krb5_ccache ccache;
+ krb5_error_code kerr;
+ krb5_principal target_principal;
+
+
+ if( argc < 2 )
+ {
+ fprintf( stderr, "Usage: setpass user@REALM\n");
+ exit(1);
+ }
+
+/*
+** verify credentials -
+*/
+ if( verify_creds() )
+ init_creds();
+ if( verify_creds() )
+ {
+ fprintf( stderr, "No user credentials available\n");
+ exit(1);
+ }
+/*
+** check the principal name -
+*/
+ krb5_init_context(&kcontext);
+ kerr = krb5_parse_name( kcontext, argv[1], &target_principal );
+
+ {
+ char * pname = NULL;
+ kerr = krb5_unparse_name( kcontext, target_principal, &pname );
+ printf( "Changing password for %s:\n", pname);
+ fflush( stdout );
+ free( pname );
+ }
+/*
+** get the new password -
+*/
+ while( !new_password )
+ {
+ new_password = getpass("Enter new password: ");
+ new_password2 = getpass("Verify new password: ");
+ if( strcmp( new_password, new_password2 ) )
+ {
+ printf("Passwords do not match\n");
+ free( new_password );
+ free( new_password2 );
+ continue;
+ }
+ }
+/*
+** change the password -
+*/
+ fprintf( stderr, "the password is %s\n", new_password );
+
+ {
+ int pw_result;
+ krb5_ccache ccache;
+ krb5_data pw_res_string, res_string;
+
+ kerr = krb5_cc_default( kcontext, &ccache );
+ if( kerr == 0 )
+ {
+ kerr = krb5_set_password_using_ccache(kcontext, ccache, new_password, target_principal,
+ &pw_result, &pw_res_string, &res_string );
+ if( kerr )
+ fprintf( stderr, "Failed: %s\n", error_message(kerr) );
+ else
+ {
+ if( pw_result )
+ {
+ fprintf( stderr, "Failed(%d)", pw_result );
+ if( pw_res_string.length > 0 )
+ fprintf( stderr, ": %s", pw_res_string.data);
+ if( res_string.length > 0 )
+ fprintf( stderr, " %s", res_string.data);
+ fprintf( stderr, "\n");
+ }
+ }
+ }
+ }
+}