~ubuntu-branches/ubuntu/precise/netatalk/precise

« back to all changes in this revision

Viewing changes to etc/uams/uams_krb4/uams_krb4.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Rittau
  • Date: 2004-01-19 12:43:49 UTC
  • Revision ID: james.westby@ubuntu.com-20040119124349-es563jbp0hk0ae51
Tags: upstream-1.6.4
ImportĀ upstreamĀ versionĀ 1.6.4

Show diffs side-by-side

added added

removed removed

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