2 * $Id: uams_krb4.c,v 1.10 2009-10-15 11:39:48 didg Exp $
4 * Copyright (c) 1990,1993 Regents of The University of Michigan.
5 * All Rights Reserved. See COPYRIGHT.
10 #endif /* HAVE_CONFIG_H */
12 #if defined( KRB ) || defined( UAM_AFSKRB )
15 #include <sys/types.h>
18 #include <sys/socket.h>
23 #include <atalk/logger.h>
24 #include <netinet/in.h>
31 #include <netatalk/endian.h>
32 #include <atalk/afp.h>
33 #include <atalk/compat.h>
34 #include <atalk/util.h>
35 #include <atalk/uam.h>
37 static C_Block seskey;
38 static Key_schedule seskeysched;
40 static char realm[ REALM_SZ ];
43 static int validseskey = 0;
44 static int logged = 0;
46 static char instance[ INST_SZ ], name[ ANAME_SZ ];
47 #endif /* UAM_AFSKRB */
53 #include <afs/venus.h>
54 #include <afs/afsint.h>
62 int32_t BeginTimestamp;
70 static void lcase( p )
81 static void ucase( p )
92 #define KRB4CMD_HELO 1
93 #define KRB4RPL_REALM 2
94 #define KRB4WRT_SESS 3
95 #define KRB4RPL_DONE 4
96 #define KRB4RPL_PRINC 5
97 #define KRB4WRT_TOKEN 6
98 #define KRB4WRT_SKIP 7
99 #define KRB4RPL_DONEMUT 8
100 #define KRB4CMD_SESS 9
101 #define KRB4CMD_TOKEN 10
102 #define KRB4CMD_SKIP 11
104 static int krb4_login(void *obj, struct passwd **uam_pwd,
105 char *ibuf, size_t ibuflen,
106 char *rbuf, size_t *rbuflen )
116 char inst[ 40 ], princ[ 40 ];
118 if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, &username, &ulen) < 0)
121 if (uam_afpserver_option(obj, UAM_OPTION_PROTOCOL, &proto, NULL) < 0)
126 LOG(log_info, logtype_default, "krb4_login: KRB4CMD_SESS" );
129 memcpy( &len, p, sizeof( u_int16_t ));
130 tkt.length = ntohs( len );
131 p += sizeof( u_int16_t );
133 if ( tkt.length <= 0 || tkt.length > MAX_KTXT_LEN ) {
135 LOG(log_info, logtype_default, "krb4_login: tkt.length = %d", tkt.length );
136 return( AFPERR_BADUAM );
139 memcpy( tkt.dat, p, tkt.length );
146 strcpy( princ, "afpserver" );
149 strcpy( princ, "rcmd" );
153 if( (rc = krb_rd_req( &tkt, princ, inst, 0, &ad, "" ))
155 LOG(log_error, logtype_default,
156 "krb4_login: krb_rd_req(): %s", krb_err_txt[ rc ] );
158 return( AFPERR_BADUAM );
161 LOG(log_info, logtype_default, "krb4_login: %s.%s@%s", ad.pname, ad.pinst,
163 strcpy( realm, ad.prealm );
164 memcpy( seskey, ad.session, sizeof( C_Block ) );
165 key_sched( (C_Block *)seskey, seskeysched );
167 strncpy( username, ad.pname, ulen );
172 *p = KRB4RPL_DONE; /* XXX */
175 if (( pwd = uam_getname( obj, ad.pname, strlen(ad.pname) )) == NULL ) {
179 if (uam_checkuser( pwd ) < 0) {
180 return AFPERR_NOTAUTH;
184 return( AFP_OK ); /* Should this be AFPERR_AUTHCONT? */
187 *p++ = KRB4RPL_PRINC;
188 len = strlen( realm );
197 if (krb_get_lrealm( realm, 1 ) != KSUCCESS ) {
198 LOG(log_error, logtype_default, "krb4_login: can't get local realm!" );
199 return( AFPERR_NOTAUTH );
201 *p++ = KRB4RPL_REALM;
203 len = strlen( realm );
211 LOG(log_info, logtype_default, "krb4_login: bad command %d", *ibuf );
212 return( AFPERR_NOTAUTH );
216 if ( setpag() < 0 ) {
218 LOG(log_error, logtype_default, "krb_login: setpag: %s", strerror(errno) );
219 return( AFPERR_BADUAM );
224 return( AFPERR_AUTHCONT );
227 static int krb4_action( void *v1, void *v2, const int i )
233 I have a hunch that problems might arise on platforms
234 with non-16bit short's and non-32bit int's
236 static int krb4_logincont(void *obj, struct passwd **uam_pwd,
237 char *ibuf, size_t ibuflen,
238 char *rbuf, size_t *rbuflen)
240 static struct passwd *pwd;
245 char *p, *username, *servername;
249 struct ClearToken ct;
252 int aint, ulen, snlen;
254 if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, &username, &ulen) < 0)
257 if (uam_afpserver_option(obj, UAM_OPTION_HOSTNAME, &servername, &snlen) < 0)
261 switch ( rc = *ibuf++ ) {
265 memcpy( &len, ibuf, sizeof( u_int16_t ) );
266 ibuf += sizeof( len );
269 memcpy( p, &aint, sizeof( int ) );
271 memcpy( p, ibuf, len );
272 pcbc_encrypt( (C_Block *)p, (C_Block *)p, len, seskeysched,
277 memcpy( &len, ibuf, sizeof( u_int16_t ) );
278 ibuf += sizeof( u_int16_t ) );
281 if ( len != sizeof( struct ClearToken ) ) {
282 LOG(log_error, logtype_default, "krb4_logincont: token too short" );
284 return( AFPERR_BADUAM );
286 memcpy( &ct, ibuf, len );
288 pcbc_encrypt( (C_Block *)&ct, (C_Block *)&ct, len,
289 seskeysched, seskey, DECRYPT );
291 aint = sizeof( struct ClearToken );
292 memcpy( p, &aint, sizeof( int ) );
294 memcpy( p, &ct, sizeof( struct ClearToken ) );
295 p += sizeof( struct ClearToken );
298 memcpy( p, &aint, sizeof( int ) );
303 p += strlen( realm ) + 1;
306 vi.in_size = p - buf;
308 vi.out_size = sizeof( buf );
310 if ( pioctl( 0, VIOCSETTOK, &vi, 0 ) < 0 ) {
311 LOG(log_error, logtype_default, "krb4_logincont: pioctl: %s", strerror(errno) );
313 return( AFPERR_BADUAM );
319 *p = KRB4RPL_DONE; /* XXX */
322 if (( pwd = uam_getname( obj, username, strlen(username) ) ) == NULL ) {
323 return( AFPERR_NOTAUTH );
326 if (uam_checkuser(pwd) < 0) {
327 return AFPERR_NOTAUTH;
334 /* read in the rest */
335 if (uam_afp_read(obj, rbuf, rbuflen, krb4_action) < 0)
339 switch ( rc = *p++ ) {
341 memcpy( &len, p, sizeof( len ));
342 tkt.length = ntohs( len );
343 p += sizeof( short );
345 if ( tkt.length <= 0 || tkt.length > MAX_KTXT_LEN ) {
346 return( AFPERR_BADUAM );
348 memcpy( tkt.dat, p, tkt.length );
351 if (( rc = krb_rd_req( &tkt, "afpserver", servername,
352 0, &ad, "" )) != RD_AP_OK ) {
353 LOG(log_error, logtype_default, "krb4_logincont: krb_rd_req(): %s", krb_err_txt[ rc ] );
354 return( AFPERR_BADUAM );
357 LOG(log_info, logtype_default, "krb4_login: %s.%s@%s", ad.pname,
358 ad.pinst, ad.prealm );
359 memcpy(realm, ad.prealm, sizeof(realm));
360 memcpy(seskey, ad.session, sizeof( C_Block ));
361 key_sched((C_Block *) seskey, seskeysched );
363 strncpy(username, ad.pname, ulen);
367 *p = KRB4RPL_DONE; /* XXX */
370 if (( pwd = uam_getname( obj, ad.pname, strlen(ad.pname) ))
372 return( AFPERR_PARAM );
378 *p++ = KRB4RPL_PRINC;
379 len = strlen( realm );
385 return( AFPERR_AUTHCONT );
388 memcpy( &len, p, sizeof( len ));
391 memcpy( &cr, p, len );
393 pcbc_encrypt((C_Block *)&cr, (C_Block *)&cr, len,
394 seskeysched, seskey, DES_DECRYPT );
397 cr.ticket_st.length = ntohl( cr.ticket_st.length );
398 memcpy( p, &cr.ticket_st.length, sizeof( int ));
400 memcpy( p, cr.ticket_st.dat, cr.ticket_st.length );
401 p += cr.ticket_st.length;
403 ct.AuthHandle = ntohl( cr.kvno );
404 memcpy( ct.HandShakeKey, cr.session, sizeof( cr.session ));
406 ct.BeginTimestamp = ntohl( cr.issue_date );
407 ct.EndTimestamp = krb_life_to_time( ntohl( cr.issue_date ),
408 ntohl( cr.lifetime ));
410 aint = sizeof( struct ClearToken );
411 memcpy( p, &aint, sizeof( int ));
413 memcpy( p, &ct, sizeof( struct ClearToken ));
414 p += sizeof( struct ClearToken );
417 memcpy( p, &aint, sizeof( int ));
422 p += strlen( realm ) + 1;
425 vi.in_size = p - buf;
427 vi.out_size = sizeof( buf );
428 if ( pioctl( 0, VIOCSETTOK, &vi, 0 ) < 0 ) {
429 LOG(log_error, logtype_default, "krb4_logincont: pioctl: %s", strerror(errno) );
430 return( AFPERR_BADUAM );
436 *p = KRB4RPL_DONE; /* XXX */
439 if (( pwd = uam_getname( obj, ad.pname, strlen(ad.pname) ))
441 return( AFPERR_PARAM );
448 LOG(log_info, logtype_default, "krb4_logincont: bad command %d", rc );
450 return( AFPERR_NOTAUTH );
461 #include <rx/rxkad.h>
462 #include <afs/afsint.h>
464 char *ka_LocalCell();
467 addrealm(realm,cells)
476 for(;*ptr != 0 ;ptr++)
477 if(!strcmp(realm,*ptr))
481 *cells=(char**)realloc(*cells,((2+temp)*sizeof(char*)));
484 *ptr=(char*)malloc(strlen(realm)+1);
485 strcpy(*ptr++,realm);
490 static int kcheckuser(pwd,passwd)
496 char realm[MAXKTCREALMLEN];
497 char lorealm[MAXKTCREALMLEN];
499 Date lifetime=MAXKTCTICKETLIFETIME;
501 char **cells=(char **)malloc(sizeof(char*));
504 struct ktc_principal serviceName;
512 temp=(char*)malloc(strlen(pwd->pw_dir)+1);
513 strcpy(temp,pwd->pw_dir);
515 temp=strtok(temp,"/");
516 temp=strtok('\0',"/");
517 ka_CellToRealm(temp,realm,0);
518 addrealm(realm,&cells);
523 authenticate(cells,pwd->pw_name,passwd);
525 rc=ktc_ListTokens(cellNum,&cellNum,&serviceName);
535 static void authenticate(cells,name,passwd)
544 ka_UserAuthenticate(name,/*instance*/"",/*cell*/*ptr++,
545 passwd,/*setpag*/0,&errorstring);
550 #if defined( UAM_AFSKRB ) && defined( AFS )
551 static int afskrb_login(void *obj, struct passwd *uam_pwd,
552 char *ibuf, size_t ibuflen,
553 char *rbuf, size_t *rbuflen )
555 KTEXT_ST authent, rpkt;
557 char *p, *q, *username, servername;
558 int len, rc, whoserealm, ulen, snlen;
562 if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, &username, &ulen) < 0)
565 if (uam_afpserver_option(obj, UAM_OPTION_HOSTNAME, &servername, &snlen ) < 0)
568 len = (unsigned char) *ibuf++;
570 if (( p = strchr( ibuf, '@' )) != NULL ) {
576 if ( krb_get_lrealm( realm, 1 ) != KSUCCESS ) {
577 return AFPERR_BADUAM;
581 if (( p = strchr( ibuf, '.' )) != NULL ) {
583 strcpy( instance, p );
587 strcpy( name, ibuf );
589 * We don't have the session key, yet. Get one.
592 if ( validseskey == 0 ) {
593 if ( setpag() < 0 ) {
594 LOG(log_error, logtype_default, "krb_login: setpag: %s", strerror(errno) );
595 return AFPERR_BADUAM;
597 krb_set_tkt_string(( tktfile = mktemp( _PATH_AFPTKT )));
598 if (( rc = krb_get_svc_in_tkt( "afpserver", servername, realm,
599 TICKET_GRANTING_TICKET, realm, 255, KEYFILE )) != INTK_OK ) {
600 LOG(log_error, logtype_default, "krb_login: can't get ticket-granting-ticket" );
601 return (( whoserealm ) ? AFPERR_BADUAM : AFPERR_PARAM );
603 if ( krb_mk_req( &authent, name, instance, realm, 0 ) != KSUCCESS ) {
604 return ( AFPERR_PARAM );
606 if ( krb_get_cred( name, instance, realm, &cr ) != KSUCCESS ) {
607 return ( AFPERR_BADUAM );
610 if ( unlink( tktfile ) < 0 ) {
611 LOG(log_error, logtype_default, "krb_login: unlink %s: %s", tktfile, strerror(errno) );
612 return ( AFPERR_BADUAM );
615 memcpy( seskey, cr.session, sizeof( C_Block ));
616 key_sched((C_Block *) seskey, seskeysched );
618 strncpy(username, name, ulen);
620 memcpy( p, authent.dat, authent.length );
624 if ( kuam_get_in_tkt( name, instance, realm, TICKET_GRANTING_TICKET,
625 realm, 255, &rpkt ) != INTK_OK ) {
626 return ( AFPERR_PARAM );
630 q = (char *)rpkt.dat;
641 len = strlen( realm );
644 memcpy( &slen, q, sizeof( short ));
645 memcpy( p, &slen, sizeof( short ));
646 p += sizeof( short );
647 q += sizeof( short );
648 memcpy( p, q, slen );
652 return( AFPERR_AUTHCONT );
655 static int afskrb_logincont(void *obj, struct passwd *uam_pwd,
656 char *ibuf, size_t ibuflen,
657 char *rbuf, size_t *rbuflen )
661 struct ClearToken ct;
663 char buf[ 1024 ], *p;
668 if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, &username, NULL) < 0)
672 memcpy( &clen, ibuf, sizeof( short ));
673 clen = ntohs( clen );
674 ibuf += sizeof( short );
676 pcbc_encrypt((C_Block *)ibuf, (C_Block *)ibuf,
677 clen, seskeysched, seskey, DES_DECRYPT );
678 if ( kuam_set_in_tkt( name, instance, realm, TICKET_GRANTING_TICKET,
679 realm, ibuf ) != INTK_OK ) {
680 return ( AFPERR_PARAM );
683 if ( get_ad_tkt( "afs", "", realm, 255 ) != KSUCCESS ) {
684 return ( AFPERR_PARAM );
686 if ( krb_get_cred( "afs", "", realm, &cr ) != KSUCCESS ) {
687 return ( AFPERR_PARAM );
691 memcpy( p, &cr.ticket_st.length, sizeof( int ));
693 memcpy( p, cr.ticket_st.dat, cr.ticket_st.length );
694 p += cr.ticket_st.length;
696 ct.AuthHandle = cr.kvno;
697 memcpy( ct.HandShakeKey, cr.session, sizeof( cr.session ));
699 ct.BeginTimestamp = cr.issue_date;
700 /* ct.EndTimestamp = cr.issue_date + ( cr.lifetime * 5 * 60 ); */
701 ct.EndTimestamp = krb_life_to_time( cr.issue_date, cr.lifetime );
703 aint = sizeof( struct ClearToken );
704 memcpy( p, &aint, sizeof( int ));
706 memcpy( p, &ct, sizeof( struct ClearToken ));
707 p += sizeof( struct ClearToken );
710 memcpy( p, &aint, sizeof( int ));
715 p += strlen( realm ) + 1;
718 vi.in_size = p - buf;
720 vi.out_size = sizeof( buf );
721 if ( pioctl( 0, VIOCSETTOK, &vi, 0 ) < 0 ) {
722 LOG(log_error, logtype_default, "krb_logincont: pioctl: %s", strerror(errno) );
723 return ( AFPERR_BADUAM );
726 if ( unlink( tktfile ) < 0 ) {
727 LOG(log_error, logtype_default, "krb_logincont: %s: %s", tktfile, strerror(errno) );
728 return ( AFPERR_BADUAM );
731 if (( pwd = uam_getname( obj, username, strlen(username) )) == NULL ) {
732 return ( AFPERR_PARAM );
737 LOG(log_info, logtype_default, "authenticated %s.%s@%s", name, instance, realm );
741 LOG(log_info, logtype_default, "re-authenticated %s.%s@%s", name, instance, realm );
744 #endif /* UAM_AFSKRB AFS */
746 static int uam_setup(const char *path)
749 uam_register(UAM_SERVER_LOGIN, path, "Kerberos IV", krb4_login,
750 krb4_logincont, NULL);
751 /* uam_afpserver_action(); */
754 uam_register(UAM_SERVER_LOGIN, path, "AFS Kerberos", afskrb_login,
755 afskrb_logincont, NULL);
756 /* uam_afpserver_action(); */
757 #endif /* UAM_AFSKRB */
761 static void uam_cleanup(void)
764 /* uam_afpserver_action(); */
765 uam_unregister(UAM_SERVER_LOGIN, "Kerberos IV");
768 /* uam_afpserver_action(); */
769 uam_unregister(UAM_SERVER_LOGIN, "AFS Kerberos");
773 UAM_MODULE_EXPORT struct uam_export uams_krb4 = {
776 uam_setup, uam_cleanup
779 #endif /* KRB or UAM_AFSKRB */