2
* $Id: uams_krb4.c,v 1.6 2002/01/04 04:45:48 sibaz 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
#endif /* HAVE_UNISTD_H */
18
#endif /* HAVE_FCNTL_H */
19
#include <sys/types.h>
22
#include <sys/socket.h>
28
#else /* STDC_HEADERS */
32
#endif /* HAVE_STRCHR */
33
char *strchr (), *strrchr ();
35
#define memcpy(d,s,n) bcopy ((s), (d), (n))
36
#define memmove(d,s,n) bcopy ((s), (d), (n))
37
#endif /* ! HAVE_MEMCPY */
38
#endif /* STDC_HEADERS */
42
#include <atalk/logger.h>
43
#include <netinet/in.h>
50
#include <netatalk/endian.h>
51
#include <atalk/afp.h>
52
#include <atalk/compat.h>
53
#include <atalk/util.h>
54
#include <atalk/uam.h>
56
static C_Block seskey;
57
static Key_schedule seskeysched;
59
static char realm[ REALM_SZ ];
62
static int validseskey = 0;
63
static int logged = 0;
65
static char instance[ INST_SZ ], name[ ANAME_SZ ];
66
#endif /* UAM_AFSKRB */
72
#include <afs/venus.h>
73
#include <afs/afsint.h>
81
int32_t BeginTimestamp;
89
static __inline__ void lcase( p )
100
static __inline__ void ucase( p )
104
if ( islower( *p )) {
111
#define KRB4CMD_HELO 1
112
#define KRB4RPL_REALM 2
113
#define KRB4WRT_SESS 3
114
#define KRB4RPL_DONE 4
115
#define KRB4RPL_PRINC 5
116
#define KRB4WRT_TOKEN 6
117
#define KRB4WRT_SKIP 7
118
#define KRB4RPL_DONEMUT 8
119
#define KRB4CMD_SESS 9
120
#define KRB4CMD_TOKEN 10
121
#define KRB4CMD_SKIP 11
123
static int krb4_login(void *obj, struct passwd **uam_pwd,
124
char *ibuf, int ibuflen,
125
char *rbuf, int *rbuflen )
134
char inst[ 40 ], princ[ 40 ];
136
if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, &username, &ulen) < 0)
139
if (uam_afpserver_option(obj, UAM_OPTION_PROTOCOL, &proto, NULL) < 0)
144
LOG(log_info, logtype_default, "krb4_login: KRB4CMD_SESS" );
147
memcpy( &len, p, sizeof( u_int16_t ));
148
tkt.length = ntohs( len );
149
p += sizeof( u_int16_t );
151
if ( tkt.length <= 0 || tkt.length > MAX_KTXT_LEN ) {
153
LOG(log_info, logtype_default, "krb4_login: tkt.length = %d", tkt.length );
154
return( AFPERR_BADUAM );
157
memcpy( tkt.dat, p, tkt.length );
164
strcpy( princ, "afpserver" );
167
strcpy( princ, "rcmd" );
171
if( (rc = krb_rd_req( &tkt, princ, inst, 0, &ad, "" ))
173
LOG(log_error, logtype_default,
174
"krb4_login: krb_rd_req(): %s", krb_err_txt[ rc ] );
176
return( AFPERR_BADUAM );
179
LOG(log_info, logtype_default, "krb4_login: %s.%s@%s", ad.pname, ad.pinst,
181
strcpy( realm, ad.prealm );
182
memcpy( seskey, ad.session, sizeof( C_Block ) );
183
key_sched( (C_Block *)seskey, seskeysched );
185
strncpy( username, ad.pname, ulen );
190
*p = KRB4RPL_DONE; /* XXX */
193
if (( pwd = uam_getname( ad.pname, strlen(ad.pname) )) == NULL ) {
197
if (uam_checkuser( pwd ) < 0) {
198
return AFPERR_NOTAUTH;
202
return( AFP_OK ); /* Should this be AFPERR_AUTHCONT? */
205
*p++ = KRB4RPL_PRINC;
206
len = strlen( realm );
215
if (krb_get_lrealm( realm, 1 ) != KSUCCESS ) {
216
LOG(log_error, logtype_default, "krb4_login: can't get local realm!" );
217
return( AFPERR_NOTAUTH );
219
*p++ = KRB4RPL_REALM;
221
len = strlen( realm );
229
LOG(log_info, logtype_default, "krb4_login: bad command %d", *ibuf );
230
return( AFPERR_NOTAUTH );
234
if ( setpag() < 0 ) {
236
LOG(log_error, logtype_default, "krb_login: setpag: %m" );
237
return( AFPERR_BADUAM );
242
return( AFPERR_AUTHCONT );
245
static int krb4_action( void *v1, void *v2, const int i )
251
I have a hunch that problems might arise on platforms
252
with non-16bit short's and non-32bit int's
254
static int krb4_logincont(void *obj, struct passwd **uam_pwd,
255
char *ibuf, int ibuflen,
256
char *rbuf, int *rbuflen)
258
static struct passwd *pwd;
263
char *p, *username, *servername;
267
struct ClearToken ct;
270
int aint, ulen, snlen;
272
if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, &username, &ulen) < 0)
275
if (uam_afpserver_option(obj, UAM_OPTION_HOSTNAME, &servername, &snlen) < 0)
279
switch ( rc = *ibuf++ ) {
283
memcpy( &len, ibuf, sizeof( u_int16_t ) );
284
ibuf += sizeof( len );
287
memcpy( p, &aint, sizeof( int ) );
289
memcpy( p, ibuf, len );
290
pcbc_encrypt( (C_Block *)p, (C_Block *)p, len, seskeysched,
295
memcpy( &len, ibuf, sizeof( u_int16_t ) );
296
ibuf += sizeof( u_int16_t ) );
299
if ( len != sizeof( struct ClearToken ) ) {
300
LOG(log_error, logtype_default, "krb4_logincont: token too short" );
302
return( AFPERR_BADUAM );
304
memcpy( &ct, ibuf, len );
306
pcbc_encrypt( (C_Block *)&ct, (C_Block *)&ct, len,
307
seskeysched, seskey, DECRYPT );
309
aint = sizeof( struct ClearToken );
310
memcpy( p, &aint, sizeof( int ) );
312
memcpy( p, &ct, sizeof( struct ClearToken ) );
313
p += sizeof( struct ClearToken );
316
memcpy( p, &aint, sizeof( int ) );
321
p += strlen( realm ) + 1;
324
vi.in_size = p - buf;
326
vi.out_size = sizeof( buf );
328
if ( pioctl( 0, VIOCSETTOK, &vi, 0 ) < 0 ) {
329
LOG(log_error, logtype_default, "krb4_logincont: pioctl: %m" );
331
return( AFPERR_BADUAM );
337
*p = KRB4RPL_DONE; /* XXX */
340
if (( pwd = uam_getname( username, strlen(username) ) ) == NULL ) {
341
return( AFPERR_NOTAUTH );
344
if (uam_checkuser(pwd) < 0) {
345
return AFPERR_NOTAUTH;
352
/* read in the rest */
353
if (uam_afp_read(obj, rbuf, rbuflen, krb4_action) < 0)
357
switch ( rc = *p++ ) {
359
memcpy( &len, p, sizeof( len ));
360
tkt.length = ntohs( len );
361
p += sizeof( short );
363
if ( tkt.length <= 0 || tkt.length > MAX_KTXT_LEN ) {
364
return( AFPERR_BADUAM );
366
memcpy( tkt.dat, p, tkt.length );
369
if (( rc = krb_rd_req( &tkt, "afpserver", servername,
370
0, &ad, "" )) != RD_AP_OK ) {
371
LOG(log_error, logtype_default, "krb4_logincont: krb_rd_req(): %s", krb_err_txt[ rc ] );
372
return( AFPERR_BADUAM );
375
LOG(log_info, logtype_default, "krb4_login: %s.%s@%s", ad.pname,
376
ad.pinst, ad.prealm );
377
memcpy(realm, ad.prealm, sizeof(realm));
378
memcpy(seskey, ad.session, sizeof( C_Block ));
379
key_sched((C_Block *) seskey, seskeysched );
381
strncpy(username, ad.pname, ulen);
385
*p = KRB4RPL_DONE; /* XXX */
388
if (( pwd = uam_getname( ad.pname, strlen(ad.pname) ))
390
return( AFPERR_PARAM );
396
*p++ = KRB4RPL_PRINC;
397
len = strlen( realm );
403
return( AFPERR_AUTHCONT );
406
memcpy( &len, p, sizeof( len ));
409
memcpy( &cr, p, len );
411
pcbc_encrypt((C_Block *)&cr, (C_Block *)&cr, len,
412
seskeysched, seskey, DES_DECRYPT );
415
cr.ticket_st.length = ntohl( cr.ticket_st.length );
416
memcpy( p, &cr.ticket_st.length, sizeof( int ));
418
memcpy( p, cr.ticket_st.dat, cr.ticket_st.length );
419
p += cr.ticket_st.length;
421
ct.AuthHandle = ntohl( cr.kvno );
422
memcpy( ct.HandShakeKey, cr.session, sizeof( cr.session ));
424
ct.BeginTimestamp = ntohl( cr.issue_date );
425
ct.EndTimestamp = krb_life_to_time( ntohl( cr.issue_date ),
426
ntohl( cr.lifetime ));
428
aint = sizeof( struct ClearToken );
429
memcpy( p, &aint, sizeof( int ));
431
memcpy( p, &ct, sizeof( struct ClearToken ));
432
p += sizeof( struct ClearToken );
435
memcpy( p, &aint, sizeof( int ));
440
p += strlen( realm ) + 1;
443
vi.in_size = p - buf;
445
vi.out_size = sizeof( buf );
446
if ( pioctl( 0, VIOCSETTOK, &vi, 0 ) < 0 ) {
447
LOG(log_error, logtype_default, "krb4_logincont: pioctl: %m" );
448
return( AFPERR_BADUAM );
454
*p = KRB4RPL_DONE; /* XXX */
457
if (( pwd = uam_getname( ad.pname, strlen(ad.pname) ))
459
return( AFPERR_PARAM );
466
LOG(log_info, logtype_default, "krb4_logincont: bad command %d", rc );
468
return( AFPERR_NOTAUTH );
479
#include <rx/rxkad.h>
480
#include <afs/afsint.h>
482
char *ka_LocalCell();
485
addrealm(realm,cells)
494
for(;*ptr != 0 ;ptr++)
495
if(!strcmp(realm,*ptr))
499
*cells=(char**)realloc(*cells,((2+temp)*sizeof(char*)));
502
*ptr=(char*)malloc(strlen(realm)+1);
503
strcpy(*ptr++,realm);
508
static int kcheckuser(pwd,passwd)
514
char realm[MAXKTCREALMLEN];
515
char lorealm[MAXKTCREALMLEN];
517
Date lifetime=MAXKTCTICKETLIFETIME;
519
char **cells=(char **)malloc(sizeof(char*));
522
struct ktc_principal serviceName;
530
temp=(char*)malloc(strlen(pwd->pw_dir)+1);
531
strcpy(temp,pwd->pw_dir);
533
temp=strtok(temp,"/");
534
temp=strtok('\0',"/");
535
ka_CellToRealm(temp,realm,0);
536
addrealm(realm,&cells);
541
authenticate(cells,pwd->pw_name,passwd);
543
rc=ktc_ListTokens(cellNum,&cellNum,&serviceName);
553
static void authenticate(cells,name,passwd)
562
ka_UserAuthenticate(name,/*instance*/"",/*cell*/*ptr++,
563
passwd,/*setpag*/0,&errorstring);
568
#if defined( UAM_AFSKRB ) && defined( AFS )
569
static int afskrb_login(void *obj, struct passwd *uam_pwd,
570
char *ibuf, int ibuflen,
571
char *rbuf, int *rbuflen )
573
KTEXT_ST authent, rpkt;
575
char *p, *q, *username, servername;
576
int len, rc, whoserealm, ulen, snlen;
580
if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, &username, &ulen) < 0)
583
if (uam_afpserver_option(obj, UAM_OPTION_HOSTNAME, &servername, &snlen ) < 0)
586
len = (unsigned char) *ibuf++;
588
if (( p = strchr( ibuf, '@' )) != NULL ) {
594
if ( krb_get_lrealm( realm, 1 ) != KSUCCESS ) {
595
return AFPERR_BADUAM;
599
if (( p = strchr( ibuf, '.' )) != NULL ) {
601
strcpy( instance, p );
605
strcpy( name, ibuf );
607
* We don't have the session key, yet. Get one.
610
if ( validseskey == 0 ) {
611
if ( setpag() < 0 ) {
612
LOG(log_error, logtype_default, "krb_login: setpag: %m" );
613
return AFPERR_BADUAM;
615
krb_set_tkt_string(( tktfile = mktemp( _PATH_AFPTKT )));
616
if (( rc = krb_get_svc_in_tkt( "afpserver", servername, realm,
617
TICKET_GRANTING_TICKET, realm, 255, KEYFILE )) != INTK_OK ) {
618
LOG(log_error, logtype_default, "krb_login: can't get ticket-granting-ticket" );
619
return (( whoserealm ) ? AFPERR_BADUAM : AFPERR_PARAM );
621
if ( krb_mk_req( &authent, name, instance, realm, 0 ) != KSUCCESS ) {
622
return ( AFPERR_PARAM );
624
if ( krb_get_cred( name, instance, realm, &cr ) != KSUCCESS ) {
625
return ( AFPERR_BADUAM );
628
if ( unlink( tktfile ) < 0 ) {
629
LOG(log_error, logtype_default, "krb_login: unlink %s: %m", tktfile );
630
return ( AFPERR_BADUAM );
633
memcpy( seskey, cr.session, sizeof( C_Block ));
634
key_sched((C_Block *) seskey, seskeysched );
636
strncpy(username, name, ulen);
638
memcpy( p, authent.dat, authent.length );
642
if ( kuam_get_in_tkt( name, instance, realm, TICKET_GRANTING_TICKET,
643
realm, 255, &rpkt ) != INTK_OK ) {
644
return ( AFPERR_PARAM );
648
q = (char *)rpkt.dat;
659
len = strlen( realm );
662
memcpy( &slen, q, sizeof( short ));
663
memcpy( p, &slen, sizeof( short ));
664
p += sizeof( short );
665
q += sizeof( short );
666
memcpy( p, q, slen );
670
return( AFPERR_AUTHCONT );
673
static int afskrb_logincont(void *obj, struct passwd *uam_pwd,
674
char *ibuf, int ibuflen,
675
char *rbuf, int *rbuflen )
679
struct ClearToken ct;
681
char buf[ 1024 ], *p;
686
if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, &username, NULL) < 0)
690
memcpy( &clen, ibuf, sizeof( short ));
691
clen = ntohs( clen );
692
ibuf += sizeof( short );
694
pcbc_encrypt((C_Block *)ibuf, (C_Block *)ibuf,
695
clen, seskeysched, seskey, DES_DECRYPT );
696
if ( kuam_set_in_tkt( name, instance, realm, TICKET_GRANTING_TICKET,
697
realm, ibuf ) != INTK_OK ) {
698
return ( AFPERR_PARAM );
701
if ( get_ad_tkt( "afs", "", realm, 255 ) != KSUCCESS ) {
702
return ( AFPERR_PARAM );
704
if ( krb_get_cred( "afs", "", realm, &cr ) != KSUCCESS ) {
705
return ( AFPERR_PARAM );
709
memcpy( p, &cr.ticket_st.length, sizeof( int ));
711
memcpy( p, cr.ticket_st.dat, cr.ticket_st.length );
712
p += cr.ticket_st.length;
714
ct.AuthHandle = cr.kvno;
715
memcpy( ct.HandShakeKey, cr.session, sizeof( cr.session ));
717
ct.BeginTimestamp = cr.issue_date;
718
/* ct.EndTimestamp = cr.issue_date + ( cr.lifetime * 5 * 60 ); */
719
ct.EndTimestamp = krb_life_to_time( cr.issue_date, cr.lifetime );
721
aint = sizeof( struct ClearToken );
722
memcpy( p, &aint, sizeof( int ));
724
memcpy( p, &ct, sizeof( struct ClearToken ));
725
p += sizeof( struct ClearToken );
728
memcpy( p, &aint, sizeof( int ));
733
p += strlen( realm ) + 1;
736
vi.in_size = p - buf;
738
vi.out_size = sizeof( buf );
739
if ( pioctl( 0, VIOCSETTOK, &vi, 0 ) < 0 ) {
740
LOG(log_error, logtype_default, "krb_logincont: pioctl: %m" );
741
return ( AFPERR_BADUAM );
744
if ( unlink( tktfile ) < 0 ) {
745
LOG(log_error, logtype_default, "krb_logincont: %s: %m", tktfile );
746
return ( AFPERR_BADUAM );
749
if (( pwd = uam_getname( username )) == NULL ) {
750
return ( AFPERR_PARAM );
755
LOG(log_info, logtype_default, "authenticated %s.%s@%s", name, instance, realm );
759
LOG(log_info, logtype_default, "re-authenticated %s.%s@%s", name, instance, realm );
762
#endif /* UAM_AFSKRB AFS */
764
static int uam_setup(const char *path)
767
uam_register(UAM_SERVER_LOGIN, path, "Kerberos IV", krb4_login,
768
krb4_logincont, NULL);
769
/* uam_afpserver_action(); */
772
uam_register(UAM_SERVER_LOGIN, path, "AFS Kerberos", afskrb_login,
773
afskrb_logincont, NULL);
774
/* uam_afpserver_action(); */
775
#endif /* UAM_AFSKRB */
779
static void uam_cleanup(void)
782
/* uam_afpserver_action(); */
783
uam_unregister(UAM_SERVER_LOGIN, "Kerberos IV");
786
/* uam_afpserver_action(); */
787
uam_unregister(UAM_SERVER_LOGIN, "AFS Kerberos");
791
UAM_MODULE_EXPORT struct uam_export uams_krb4 = {
794
uam_setup, uam_cleanup
797
#endif /* KRB or UAM_AFSKRB */