]> arthur.barton.de Git - netatalk.git/blob - etc/uams/uams_krb4/uams_krb4.c
d377b466007d8506104132e089abb4f3e53a90dc
[netatalk.git] / etc / uams / uams_krb4 / uams_krb4.c
1 /*
2  * $Id: uams_krb4.c,v 1.3 2001-03-28 22:49:25 samnoble Exp $
3  *
4  * Copyright (c) 1990,1993 Regents of The University of Michigan.
5  * All Rights Reserved.  See COPYRIGHT.
6  */
7
8 #if defined(HAVE_CONFIG_H)
9 #include "config.h"
10 #endif
11
12 #if defined( KRB ) || defined( UAM_AFSKRB )
13 #include <unistd.h>
14 #include <fcntl.h>
15 #include <sys/types.h>
16 #include <sys/time.h>
17 #include <sys/stat.h>
18 #include <sys/socket.h>
19 #include <limits.h>
20 #include <string.h>
21 #include <ctype.h>
22 #include <pwd.h>
23 #include <syslog.h>
24 #include <netinet/in.h>
25 #include <des.h>
26 #include <krb.h>
27 #if 0
28 #include <prot.h>
29 #endif
30
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>
36
37 static C_Block                  seskey;
38 static Key_schedule             seskeysched;
39
40 static char             realm[ REALM_SZ ];
41
42 #ifdef UAM_AFSKRB
43 static int              validseskey = 0;
44 static int              logged = 0;
45 static char             *tktfile;
46 static char             instance[ INST_SZ ], name[ ANAME_SZ ];
47 #endif /*UAM_AFSKRB*/
48
49 #ifdef AFS
50 #include <afs/stds.h>
51 #include <rx/rxkad.h>
52 #include <afs/afs.h>
53 #include <afs/venus.h>
54 #include <afs/afsint.h>
55
56 char *ka_LocalCell();
57
58 struct ClearToken {
59     int32_t AuthHandle;
60     char HandShakeKey[8];
61     int32_t ViceId;
62     int32_t BeginTimestamp;
63     int32_t EndTimestamp;
64 };
65 #endif /*AFS*/
66
67
68 #ifdef KRB
69
70 static __inline__ void lcase( p )
71     char        *p;
72 {
73     for (; *p; p++ ) {
74         if ( isupper( *p )) {
75             *p = tolower( *p );
76         }
77     }
78     return;
79 }
80
81 static __inline__ void ucase( p )
82     char        *p;
83 {
84     for (; *p; p++ ) {
85         if ( islower( *p )) {
86             *p = toupper( *p );
87         }
88     }
89     return;
90 }
91
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
103
104 static int krb4_login(void *obj, struct passwd **uam_pwd,
105                       char *ibuf, int ibuflen,
106                       char *rbuf, int *rbuflen )
107 {
108     char                *p;
109     char                *username;
110     struct passwd       *pwd;
111     u_int16_t           len;
112     KTEXT_ST            tkt;
113     static AUTH_DAT     ad;
114     int                 rc, ulen, proto;
115     char                inst[ 40 ], princ[ 40 ];
116
117     if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, &username, &ulen) < 0)
118       return AFPERR_MISC;
119
120     if (uam_afpserver_option(obj, UAM_OPTION_PROTOCOL, &proto, NULL) < 0)
121       return AFPERR_MISC;
122
123     switch( *ibuf ) {
124         case KRB4CMD_SESS:
125             syslog( LOG_INFO, "krb4_login: KRB4CMD_SESS" );
126             ++ibuf;
127             p = ibuf;
128             memcpy( &len, p, sizeof( u_int16_t ));
129             tkt.length = ntohs( len );
130             p += sizeof( u_int16_t );
131
132             if ( tkt.length <= 0 || tkt.length > MAX_KTXT_LEN ) {
133                 *rbuflen = 0;
134                 syslog( LOG_INFO, "krb4_login: tkt.length = %d", tkt.length );
135                 return( AFPERR_BADUAM );
136             }
137
138             memcpy( tkt.dat, p, tkt.length );
139             p += tkt.length;
140
141             strcpy( inst, "*" );
142
143             switch( proto ) {
144                 case AFPPROTO_ASP:
145                     strcpy( princ, "afpserver" );
146                     break;
147                 case AFPPROTO_DSI:
148                     strcpy( princ, "rcmd" );
149                     break;
150             }
151
152             if( (rc = krb_rd_req( &tkt, princ, inst, 0, &ad, "" )) 
153                 != RD_AP_OK ) {
154                 syslog( LOG_ERR, 
155                         "krb4_login: krb_rd_req(): %s", krb_err_txt[ rc ] );
156                 *rbuflen = 0;
157                 return( AFPERR_BADUAM );
158             }
159
160             syslog( LOG_INFO, "krb4_login: %s.%s@%s", ad.pname, ad.pinst, 
161                 ad.prealm );
162             strcpy( realm, ad.prealm );
163             memcpy( seskey, ad.session, sizeof( C_Block ) );
164             key_sched( (C_Block *)seskey, seskeysched );
165
166             strncpy( username, ad.pname, ulen );
167
168             p = rbuf;
169
170 #if !defined( AFS )
171             *p = KRB4RPL_DONE;  /* XXX */
172             *rbuflen = 1;
173
174             if (( pwd = uam_getname( ad.pname, strlen(ad.pname) )) == NULL ) {
175                 return AFPERR_PARAM;
176             }
177 /*
178             if (uam_checkuser( pwd ) < 0) {
179                 return AFPERR_NOTAUTH;
180             }
181 */
182             *uam_pwd = pwd;
183             return( AFP_OK ); /* Should this be AFPERR_AUTHCONT? */
184 #else /* AFS */
185             /* get principals */
186             *p++ = KRB4RPL_PRINC;
187             len = strlen( realm );
188             *p++ = len + 1;
189             *p++ = '@';
190             strcpy( p, realm );
191             p += len + 1;
192             break;
193 #endif /* AFS */
194         case KRB4CMD_HELO:
195             p = rbuf;
196             if (krb_get_lrealm( realm, 1 ) != KSUCCESS ) {
197                 syslog( LOG_ERR, "krb4_login: can't get local realm!" );
198                 return( AFPERR_NOTAUTH );
199             }
200             *p++ = KRB4RPL_REALM;
201             *p++ = 1;
202             len = strlen( realm );
203             *p++ = len;
204             strcpy( p, realm );
205             p += len + 1;
206             break;
207
208         default:
209             *rbuflen = 0;
210             syslog( LOG_INFO, "krb4_login: bad command %d", *ibuf );
211             return( AFPERR_NOTAUTH );
212     }
213
214 #if defined( AFS )
215     if ( setpag() < 0 ) {
216         *rbuflen = 0;
217         syslog( LOG_ERR, "krb_login: setpag: %m" );
218         return( AFPERR_BADUAM );
219     }
220 #endif /*AFS*/
221
222     *rbuflen = p - rbuf;
223     return( AFPERR_AUTHCONT );
224 }
225
226 static int krb4_action( void *v1, void *v2, const int i )
227 {
228         return i;
229 }
230
231 /*
232    I have a hunch that problems might arise on platforms 
233    with non-16bit short's and non-32bit int's
234 */
235 static int krb4_logincont(void *obj, struct passwd **uam_pwd,
236                           char *ibuf, int ibuflen,
237                           char *rbuf, int *rbuflen)
238 {
239     static struct passwd        *pwd;
240     KTEXT_ST            tkt;
241     static AUTH_DAT     ad;
242     int                 rc;
243     u_int16_t           len;
244     char                *p, *username, *servername;
245     CREDENTIALS         cr;
246 #ifdef AFS
247     struct ViceIoctl    vi;
248     struct ClearToken   ct;
249 #endif /*AFS*/
250     char                buf[ 1024 ];
251     int                 aint, ulen, snlen;
252
253     if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, &username, &ulen) < 0)
254       return AFPERR_MISC;
255
256     if (uam_afpserver_option(obj, UAM_OPTION_HOSTNAME, &servername, &snlen) < 0)
257       return AFPERR_MISC;
258
259     ibuf++;
260     switch ( rc = *ibuf++ ) {
261         case KRB4CMD_TOKEN :
262 #if defined (AFS)
263             p = buf;
264             memcpy( &len, ibuf, sizeof( u_int16_t ) );
265             ibuf += sizeof( len );
266             len = ntohs( len );
267             aint = len;
268             memcpy( p, &aint, sizeof( int ) );
269             p += sizeof( int );
270             memcpy( p, ibuf, len );
271             pcbc_encrypt( (C_Block *)p, (C_Block *)p, len, seskeysched,
272                 seskey, DECRYPT );
273             p += len;
274             ibuf += len;
275
276             memcpy( &len, ibuf, sizeof( u_int16_t ) );
277             ibuf += sizeof( u_int16_t ) );
278             len = ntohs( len );
279
280             if ( len != sizeof( struct ClearToken ) ) {
281                 syslog( LOG_ERR, "krb4_logincont: token too short" );
282                 *rbuflen = 0;
283                 return( AFPERR_BADUAM );
284             }
285             memcpy( &ct, ibuf, len );
286
287             pcbc_encrypt( (C_Block *)&ct, (C_Block *)&ct, len, 
288                 seskeysched, seskey, DECRYPT );
289
290             aint = sizeof( struct ClearToken );
291             memcpy( p, &aint, sizeof( int ) );
292             p += sizeof( int );
293             memcpy( p, &ct, sizeof( struct ClearToken ) );
294             p += sizeof( struct ClearToken );
295
296             aint = 0;
297             memcpy( p, &aint, sizeof( int ) );
298             p += sizeof( int );
299
300             lcase( realm );
301             strcpy( p, realm );
302             p += strlen( realm ) + 1;
303
304             vi.in = buf;
305             vi.in_size = p - buf;
306             vi.out = buf;
307             vi.out_size = sizeof( buf );
308
309             if ( pioctl( 0, VIOCSETTOK, &vi, 0 ) < 0 ) {
310                 syslog( LOG_ERR, "krb4_logincont: pioctl: %m" );
311                 *rbuflen = 0;
312                 return( AFPERR_BADUAM );
313             }
314             /* FALL THROUGH */
315
316         case KRB4CMD_SKIP:
317             p = rbuf;
318             *p = KRB4RPL_DONE;  /* XXX */
319             *rbuflen = 1;
320
321             if (( pwd = uam_getname( username, strlen(username) ) ) == NULL ) {
322                 return( AFPERR_NOTAUTH );
323             }
324 /*
325             if (uam_checkuser(pwd) < 0) {
326                 return AFPERR_NOTAUTH;
327             }
328 */
329             *uam_pwd = pwd;
330             return( AFP_OK );
331 #endif /* AFS */
332         default:
333             /* read in the rest */
334             if (uam_afp_read(obj, rbuf, rbuflen, krb4_action) < 0)
335                 return AFPERR_PARAM;
336
337             p = rbuf;
338             switch ( rc = *p++ ) {
339                 case KRB4WRT_SESS :
340                     memcpy( &len, p, sizeof( len ));
341                     tkt.length = ntohs( len );
342                     p += sizeof( short );
343
344                     if ( tkt.length <= 0 || tkt.length > MAX_KTXT_LEN ) {
345                         return( AFPERR_BADUAM );
346                     }
347                     memcpy( tkt.dat, p, tkt.length );
348                     p += tkt.length;
349
350                     if (( rc = krb_rd_req( &tkt, "afpserver", servername, 
351                         0, &ad, "" )) != RD_AP_OK ) {
352                         syslog( LOG_ERR, "krb4_logincont: krb_rd_req(): %s", krb_err_txt[ rc ] );
353                         return( AFPERR_BADUAM );
354                     }
355
356                     syslog( LOG_INFO, "krb4_login: %s.%s@%s", ad.pname, 
357                         ad.pinst, ad.prealm );
358                     memcpy(realm, ad.prealm, sizeof(realm));
359                     memcpy(seskey, ad.session, sizeof( C_Block ));
360                     key_sched((C_Block *) seskey, seskeysched );
361
362                     strncpy(username, ad.pname, ulen);
363
364                     p = rbuf;
365 #ifndef AFS
366                     *p = KRB4RPL_DONE;  /* XXX */
367                     *rbuflen = 1;
368
369                     if (( pwd = uam_getname( ad.pname, strlen(ad.pname) )) 
370                         == NULL ) {
371                         return( AFPERR_PARAM );
372                     }
373                     *uam_pwd = pwd;
374                     return AFP_OK;
375 #else AFS
376                     /* get principals */
377                     *p++ = KRB4RPL_PRINC;
378                     len = strlen( realm );
379                     *p++ = len + 1;
380                     *p++ = '@';
381                     strcpy( p, realm );
382                     p += len + 1;
383                     *rbuflen = p - rbuf;
384                     return( AFPERR_AUTHCONT );
385
386                 case KRB4WRT_TOKEN :
387                     memcpy( &len, p, sizeof( len ));
388                     len = ntohs( len );
389                     p += sizeof( len );
390                     memcpy( &cr, p, len );
391
392                     pcbc_encrypt((C_Block *)&cr, (C_Block *)&cr, len, 
393                         seskeysched, seskey, DES_DECRYPT );
394
395                     p = buf;
396                     cr.ticket_st.length = ntohl( cr.ticket_st.length );
397                     memcpy( p, &cr.ticket_st.length, sizeof( int ));
398                     p += sizeof( int );
399                     memcpy( p, cr.ticket_st.dat, cr.ticket_st.length );
400                     p += cr.ticket_st.length;
401
402                     ct.AuthHandle = ntohl( cr.kvno );
403                     memcpy( ct.HandShakeKey, cr.session, sizeof( cr.session ));
404                     ct.ViceId = 0;
405                     ct.BeginTimestamp = ntohl( cr.issue_date );
406                     ct.EndTimestamp = krb_life_to_time( ntohl( cr.issue_date ),
407                     ntohl( cr.lifetime ));
408
409                     aint = sizeof( struct ClearToken );
410                     memcpy( p, &aint, sizeof( int ));
411                     p += sizeof( int );
412                     memcpy( p, &ct, sizeof( struct ClearToken ));
413                     p += sizeof( struct ClearToken );
414
415                     aint = 0;
416                     memcpy( p, &aint, sizeof( int ));
417                     p += sizeof( int );
418
419                     lcase( realm );
420                     strcpy( p, realm );
421                     p += strlen( realm ) + 1;
422
423                     vi.in = buf;
424                     vi.in_size = p - buf;
425                     vi.out = buf;
426                     vi.out_size = sizeof( buf );
427                     if ( pioctl( 0, VIOCSETTOK, &vi, 0 ) < 0 ) {
428                         syslog( LOG_ERR, "krb4_logincont: pioctl: %m" );
429                         return( AFPERR_BADUAM );
430                     }
431                     /* FALL THROUGH */
432
433                 case KRB4WRT_SKIP :
434                     p = rbuf;
435                     *p = KRB4RPL_DONE;  /* XXX */
436                     *rbuflen = 1;
437
438                     if (( pwd = uam_getname( ad.pname, strlen(ad.pname) )) 
439                         == NULL ) {
440                         return( AFPERR_PARAM );
441                     }
442                     *uam_pwd = pwd;
443                     return AFP_OK;
444 #endif /*AFS*/
445
446                 default:
447                     syslog( LOG_INFO, "krb4_logincont: bad command %d", rc );
448                     *rbuflen = 0;
449                     return( AFPERR_NOTAUTH );
450                     break;
451             }
452             break;
453     }
454 }
455
456 #endif /*KRB*/
457
458
459 #ifdef AFS
460 #include <rx/rxkad.h>
461 #include <afs/afsint.h>
462
463 char *ka_LocalCell();
464
465 static void
466 addrealm(realm,cells)
467     char *realm;
468         char ***cells;
469 {
470     char **ptr;
471         int temp;
472
473         ptr= *cells;
474
475     for(;*ptr != 0 ;ptr++)
476         if(!strcmp(realm,*ptr))
477             return;
478
479         temp=ptr- *cells;
480         *cells=(char**)realloc(*cells,((2+temp)*sizeof(char*)));
481         ptr= *cells+temp;
482
483     *ptr=(char*)malloc(strlen(realm)+1);
484     strcpy(*ptr++,realm);
485         *ptr=0;
486     return;
487 }
488
489 static int kcheckuser(pwd,passwd)
490         struct passwd *pwd;
491         char *passwd;
492 {
493         int32_t code;
494         char *instance="";
495         char realm[MAXKTCREALMLEN];
496         char lorealm[MAXKTCREALMLEN];
497         char *cell;
498         Date lifetime=MAXKTCTICKETLIFETIME;
499         int rval;
500         char **cells=(char **)malloc(sizeof(char*));
501         char *temp;
502         int rc,cellNum;
503         struct ktc_principal serviceName;
504
505         *cells=0;
506
507         code = ka_Init(0);
508
509         {
510                 char *temp,*temp1;
511                 temp=(char*)malloc(strlen(pwd->pw_dir)+1);
512                 strcpy(temp,pwd->pw_dir);
513                 temp1=temp;
514                 temp=strtok(temp,"/");
515                 temp=strtok('\0',"/");
516                 ka_CellToRealm(temp,realm,0);
517                 addrealm(realm,&cells);
518                 free(temp1);
519         }
520
521         setpag();
522         authenticate(cells,pwd->pw_name,passwd);
523         cellNum=0;
524         rc=ktc_ListTokens(cellNum,&cellNum,&serviceName);
525         if(rc)
526                 rval=1;
527         else{
528                 rval=0;
529         }
530
531         return(rval);
532 }
533
534 static void authenticate(cells,name,passwd)
535         char **cells;
536         char *name;
537         char *passwd;
538 {
539         char **ptr=cells;
540         char *errorstring;
541
542         while(*ptr){
543             ka_UserAuthenticate(name,/*instance*/"",/*cell*/*ptr++,
544                     passwd,/*setpag*/0,&errorstring);
545         }
546 }
547 #endif /*AFS*/
548
549 #if defined( UAM_AFSKRB ) && defined( AFS )
550 static int afskrb_login(void *obj, struct passwd *uam_pwd,
551                         char *ibuf, int ibuflen, 
552                         char *rbuf, int *rbuflen )
553 {
554     KTEXT_ST    authent, rpkt;
555     CREDENTIALS cr;
556     char        *p, *q, *username, servername;
557     int         len, rc, whoserealm, ulen, snlen;
558     short       slen;
559
560     *rbuflen = 0;
561     if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, &username, &ulen) < 0)
562       return AFPERR_MISC;
563
564     if (uam_afpserver_option(obj, UAM_OPTION_HOSTNAME, &servername, &snlen ) < 0)
565       return AFPERR_MISC;
566     
567     len = (unsigned char) *ibuf++;
568     ibuf[ len ] = '\0';
569     if (( p = strchr( ibuf, '@' )) != NULL ) {
570         *p++ = '\0';
571         strcpy( realm, p );
572         ucase( realm );
573         whoserealm = 0;
574     } else {
575         if ( krb_get_lrealm( realm, 1 ) != KSUCCESS ) {
576             return AFPERR_BADUAM;
577         }
578         whoserealm = 1;
579     }
580     if (( p = strchr( ibuf, '.' )) != NULL ) {
581         *p++ = '\0';
582         strcpy( instance, p );
583     } else {
584         *instance = '\0';
585     }
586     strcpy( name, ibuf );
587     /*
588      * We don't have the session key, yet. Get one.
589      */
590     p = rbuf;
591     if ( validseskey == 0 ) {
592         if ( setpag() < 0 ) {
593             syslog( LOG_ERR, "krb_login: setpag: %m" );
594             return AFPERR_BADUAM;
595         }
596         krb_set_tkt_string(( tktfile = mktemp( _PATH_AFPTKT )));
597         if (( rc =  krb_get_svc_in_tkt( "afpserver", servername, realm,
598                 TICKET_GRANTING_TICKET, realm, 255, KEYFILE )) != INTK_OK ) {
599             syslog( LOG_ERR, "krb_login: can't get ticket-granting-ticket" );
600             return (( whoserealm ) ? AFPERR_BADUAM : AFPERR_PARAM );
601         }
602         if ( krb_mk_req( &authent, name, instance, realm, 0 ) != KSUCCESS ) {
603             return ( AFPERR_PARAM );
604         }
605         if ( krb_get_cred( name, instance, realm, &cr ) != KSUCCESS ) {
606             return ( AFPERR_BADUAM );
607         }
608
609         if ( unlink( tktfile ) < 0 ) {
610             syslog( LOG_ERR, "krb_login: unlink %s: %m", tktfile );
611             return ( AFPERR_BADUAM );
612         }
613
614         memcpy( seskey, cr.session, sizeof( C_Block ));
615         key_sched((C_Block *) seskey, seskeysched );
616         validseskey = 1;
617         strncpy(username, name, ulen);
618
619         memcpy( p, authent.dat, authent.length );
620         p += authent.length;
621     }
622
623     if ( kuam_get_in_tkt( name, instance, realm, TICKET_GRANTING_TICKET,
624             realm, 255, &rpkt ) != INTK_OK ) {
625         return ( AFPERR_PARAM );
626     }
627
628
629     q = (char *)rpkt.dat;
630     *p++ = *q++;
631     *p++ = *q++;
632     while ( *q++ )
633         ;
634     while ( *q++ )
635         ;
636     while ( *q++ )
637         ;
638     q += 10;
639
640     len = strlen( realm );
641     strcpy( p, realm );
642     p += len + 1;
643     memcpy( &slen, q, sizeof( short ));
644     memcpy( p, &slen, sizeof( short ));
645     p += sizeof( short );
646     q += sizeof( short );
647     memcpy( p, q, slen );
648     p += slen;
649
650     *rbuflen = p - rbuf;
651     return( AFPERR_AUTHCONT );
652 }
653
654 static int afskrb_logincont(void *obj, struct passwd *uam_pwd,
655                             char *ibuf, int ibuflen, 
656                             char *rbuf, int *rbuflen )
657 {
658     CREDENTIALS         cr;
659     struct ViceIoctl    vi;
660     struct ClearToken   ct;
661     struct passwd       *pwd;
662     char                buf[ 1024 ], *p;
663     int                 aint;
664     short               clen;
665
666     *rbuflen = 0;
667     if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, &username, NULL) < 0)
668       return AFPERR_MISC;
669     
670     ibuf += 2;
671     memcpy( &clen, ibuf, sizeof( short ));
672     clen = ntohs( clen );
673     ibuf += sizeof( short );
674
675     pcbc_encrypt((C_Block *)ibuf, (C_Block *)ibuf,
676             clen, seskeysched, seskey, DES_DECRYPT );
677     if ( kuam_set_in_tkt( name, instance, realm, TICKET_GRANTING_TICKET,
678             realm, ibuf ) != INTK_OK ) {
679         return ( AFPERR_PARAM );
680     }
681
682     if ( get_ad_tkt( "afs", "", realm, 255 ) != KSUCCESS ) {
683         return ( AFPERR_PARAM );
684     }
685     if ( krb_get_cred( "afs", "", realm, &cr ) != KSUCCESS ) {
686         return ( AFPERR_PARAM );
687     }
688
689     p = buf;
690     memcpy( p, &cr.ticket_st.length, sizeof( int ));
691     p += sizeof( int );
692     memcpy( p, cr.ticket_st.dat, cr.ticket_st.length );
693     p += cr.ticket_st.length;
694
695     ct.AuthHandle = cr.kvno;
696     memcpy( ct.HandShakeKey, cr.session, sizeof( cr.session ));
697     ct.ViceId = 0;
698     ct.BeginTimestamp = cr.issue_date;
699     /* ct.EndTimestamp = cr.issue_date + ( cr.lifetime * 5 * 60 ); */
700     ct.EndTimestamp = krb_life_to_time( cr.issue_date, cr.lifetime );
701
702     aint = sizeof( struct ClearToken );
703     memcpy( p, &aint, sizeof( int ));
704     p += sizeof( int );
705     memcpy( p, &ct, sizeof( struct ClearToken ));
706     p += sizeof( struct ClearToken );
707
708     aint = 0;
709     memcpy( p, &aint, sizeof( int ));
710     p += sizeof( int );
711
712     lcase( realm );
713     strcpy( p, realm );
714     p += strlen( realm ) + 1;
715
716     vi.in = buf;
717     vi.in_size = p - buf;
718     vi.out = buf;
719     vi.out_size = sizeof( buf );
720     if ( pioctl( 0, VIOCSETTOK, &vi, 0 ) < 0 ) {
721         syslog( LOG_ERR, "krb_logincont: pioctl: %m" );
722         return ( AFPERR_BADUAM );
723     }
724
725     if ( unlink( tktfile ) < 0 ) {
726         syslog( LOG_ERR, "krb_logincont: %s: %m", tktfile );
727         return ( AFPERR_BADUAM );
728     }
729
730     if (( pwd = uam_getname( username )) == NULL ) {
731         return ( AFPERR_PARAM );
732     }
733
734     if ( logged == 0 ) {
735         logged = 1;
736         syslog( LOG_INFO, "authenticated %s.%s@%s", name, instance, realm );
737         *uam_pwd = pwd;
738         return AFP_OK;
739     }
740     syslog( LOG_INFO, "re-authenticated %s.%s@%s", name, instance, realm );
741     return( AFP_OK );
742 }
743 #endif /* UAM_AFSKRB AFS */
744
745 static int uam_setup(const char *path)
746 {
747 #ifdef KRB
748    uam_register(UAM_SERVER_LOGIN, path, "Kerberos IV", krb4_login, 
749                 krb4_logincont, NULL);
750    /* uam_afpserver_action(); */
751 #endif
752 #ifdef UAM_AFSKRB
753    uam_register(UAM_SERVER_LOGIN, path, "AFS Kerberos", afskrb_login, 
754                 afskrb_logincont, NULL);
755    /* uam_afpserver_action(); */
756 #endif
757    return 0;
758 }
759
760 static void uam_cleanup(void)
761 {
762 #ifdef KRB
763    /* uam_afpserver_action(); */
764    uam_unregister(UAM_SERVER_LOGIN, "Kerberos IV");
765 #endif
766 #ifdef UAM_AFSKRB
767    /* uam_afpserver_action(); */
768    uam_unregister(UAM_SERVER_LOGIN, "AFS Kerberos");
769 #endif
770 }
771
772 UAM_MODULE_EXPORT struct uam_export uams_krb4 = {
773   UAM_MODULE_SERVER,
774   UAM_MODULE_VERSION,
775   uam_setup, uam_cleanup
776 };
777
778 #endif /* KRB or UAM_AFSKRB */
779