~ubuntu-branches/ubuntu/oneiric/openafs/oneiric-201305130334

« back to all changes in this revision

Viewing changes to src/aklog/aklog_main.c

  • Committer: Bazaar Package Importer
  • Author(s): Russ Allbery
  • Date: 2008-09-22 19:07:02 UTC
  • mfrom: (12.1.14 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080922190702-59m13d7kn6gkw32d
Tags: 1.4.7.dfsg1-6
* Apply upstream patch to free /proc entries in the correct order.
  Thanks, Marc Dionne.  (Closes: #493914)
* Apply upstream deltas to support 2.6.27 kernels and to stop using
  COMMON_KERN_CFLAGS for all 2.6 kernels uniformly, which fixes
  problems on amd64 with newer kernels.  Thanks, Björn Torkelsson.
  (LP: #267504)
* Translation updates:
  - Swedish, thanks Martin Bagge.  (Closes: #493120)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* 
2
 
 * $Id: aklog_main.c,v 1.1.2.14 2006/08/29 19:19:05 shadow Exp $
 
2
 * $Id: aklog_main.c,v 1.1.2.26 2008/04/01 18:15:53 shadow Exp $
3
3
 *
4
4
 * Copyright 1990,1991 by the Massachusetts Institute of Technology
5
5
 * For distribution and copying rights, see the file "mit-copyright.h"
6
6
 */
7
 
 
8
 
#if !defined(lint) && !defined(SABER)
9
 
static char *rcsid =
10
 
        "$Id: aklog_main.c,v 1.1.2.14 2006/08/29 19:19:05 shadow Exp $";
11
 
#endif /* lint || SABER */
 
7
/*
 
8
 * Copyright (c) 2005, 2006                                     
 
9
 * The Linux Box Corporation                                    
 
10
 * ALL RIGHTS RESERVED                                          
 
11
 *                                                              
 
12
 * Permission is granted to use, copy, create derivative works  
 
13
 * and redistribute this software and such derivative works     
 
14
 * for any purpose, so long as the name of the Linux Box        
 
15
 * Corporation is not used in any advertising or publicity      
 
16
 * pertaining to the use or distribution of this software       
 
17
 * without specific, written prior authorization.  If the       
 
18
 * above copyright notice or any other identification of the    
 
19
 * Linux Box Corporation is included in any copy of any         
 
20
 * portion of this software, then the disclaimer below must     
 
21
 * also be included.                                            
 
22
 *                                                              
 
23
 * This software is provided as is, without representation      
 
24
 * from the Linux Box Corporation as to its fitness for any     
 
25
 * purpose, and without warranty by the Linux Box Corporation   
 
26
 * of any kind, either express or implied, including            
 
27
 * without limitation the implied warranties of                 
 
28
 * merchantability and fitness for a particular purpose.  The   
 
29
 * regents of the Linux Box Corporation shall not be liable     
 
30
 * for any damages, including special, indirect, incidental, or 
 
31
 * consequential damages, with respect to any claim arising     
 
32
 * out of or in connection with the use of the software, even   
 
33
 * if it has been or is hereafter advised of the possibility of 
 
34
 * such damages.                                                
 
35
 */
12
36
 
13
37
#include <afsconfig.h>
 
38
RCSID
 
39
     ("$Header: /cvs/openafs/src/aklog/aklog_main.c,v 1.1.2.26 2008/04/01 18:15:53 shadow Exp $");
14
40
#include <stdio.h>
15
41
#include <string.h>
16
42
#include <ctype.h>
29
55
#include <sys/stat.h>
30
56
#include <fcntl.h>
31
57
 
32
 
#ifndef WINDOWS
33
58
#include <sys/param.h>
34
59
#include <sys/errno.h>
35
60
#include <netdb.h>
37
62
#include <netinet/in.h>
38
63
#include <arpa/inet.h>
39
64
#include <pwd.h>
40
 
#endif /* WINDOWS */
41
 
 
42
 
/* on AIX AFS has an unresolved reference to osi_audit. We will define
43
 
 * it here as extern. It also trys to call the ntohl and htonl routines
44
 
 * as routines rather then macros. We need a real routine here. 
45
 
 * We do this before the ntohl and htonl macros are defined in net/in.h
46
 
 */
47
 
int osi_audit()
48
 
    { return(0);}
49
 
 
50
 
#if 0
51
 
#ifdef _AIX
52
 
u_long htonl(u_long x)
53
 
    { return(x);}
54
 
 
55
 
u_long ntohl(u_long x)
56
 
    { return(x);}
57
 
#endif
58
 
 
59
 
#include <netinet/in.h>
60
 
/* #include <krb.h> */
61
 
#endif /* 0 */
62
65
 
63
66
#include <afs/stds.h>
64
67
#include <krb5.h>
65
68
 
66
 
#ifdef WINDOWS
67
 
 
68
 
#include <afs/auth.h>
69
 
#include <rx/rxkad.h>
70
 
#include <afs/dirpath.h>
71
 
 
72
 
#else /* !WINDOWS */
73
69
#ifndef HAVE_KERBEROSV_HEIM_ERR_H
74
70
#include <afs/com_err.h>
75
71
#endif
85
81
#include <afs/ptserver.h>
86
82
#include <afs/ptuser.h>
87
83
#include <afs/dirpath.h>
88
 
#endif /* WINDOWS */
89
84
 
90
85
#include "aklog.h"
91
86
#include "linked_list.h"
92
87
 
 
88
#ifdef HAVE_KRB5_CREDS_KEYBLOCK
 
89
#define USING_MIT 1
 
90
#endif
 
91
#ifdef HAVE_KRB5_CREDS_SESSION
 
92
#define USING_HEIMDAL 1
 
93
#endif
 
94
 
93
95
#define AFSKEY "afs"
94
96
#define AFSINST ""
95
97
 
97
99
#define AFS_TRY_FULL_PRINC 1
98
100
#endif /* AFS_TRY_FULL_PRINC */
99
101
 
 
102
#define AKLOG_TRYAGAIN -1
100
103
#define AKLOG_SUCCESS 0
101
104
#define AKLOG_USAGE 1
102
105
#define AKLOG_SOMETHINGSWRONG 2
138
141
static char linkedcell2[MAXCELLCHARS+1];
139
142
static krb5_ccache  _krb425_ccache = NULL;
140
143
 
141
 
#ifdef WINDOWS
142
 
 
143
 
/* libafsconf.dll */
144
 
extern long cm_GetRootCellName();
145
 
extern long cm_SearchCellFile();
146
 
 
147
 
static long cm_SearchCellFile_CallBack();
148
 
 
149
 
#else /* !WINDOWS */
150
 
 
151
144
/*
152
145
 * Why doesn't AFS provide these prototypes?
153
146
 */
158
151
 * Other prototypes
159
152
 */
160
153
 
161
 
extern char *afs_realm_of_cell(krb5_context, struct afsconf_cell *);
 
154
extern char *afs_realm_of_cell(krb5_context, struct afsconf_cell *, int);
162
155
static int isdir(char *, unsigned char *);
163
156
static krb5_error_code get_credv5(krb5_context context, char *, char *,
164
157
                                  char *, krb5_creds **);
165
158
static int get_user_realm(krb5_context, char *);
166
159
 
 
160
#define TRYAGAIN(x) (x == AKLOG_TRYAGAIN || \
 
161
                     x == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || \
 
162
                     x == KRB5KRB_ERR_GENERIC)
 
163
 
167
164
#if defined(HAVE_KRB5_PRINC_SIZE) || defined(krb5_princ_size)
168
165
 
169
166
#define get_princ_str(c, p, n) krb5_princ_component(c, p, n)->data
184
181
#error "Must have either krb5_princ_size or krb5_principal_get_comp_string"
185
182
#endif
186
183
 
 
184
#if !defined(HAVE_KRB5_ENCRYPT_TKT_PART) && defined(HAVE_ENCODE_KRB5_ENC_TKT_PART) && defined(HAVE_KRB5_C_ENCRYPT) 
 
185
krb5_error_code
 
186
krb5_encrypt_tkt_part(krb5_context context,
 
187
                      const krb5_keyblock *key,
 
188
                      krb5_ticket *ticket)
 
189
{
 
190
    krb5_data *data = 0;
 
191
    int code;
 
192
    size_t enclen;
 
193
    
 
194
    if ((code = encode_krb5_enc_tkt_part(ticket->enc_part2, &data)))
 
195
        goto Done;
 
196
    if ((code = krb5_c_encrypt_length(context, key->enctype,
 
197
                                      data->length, &enclen)))
 
198
        goto Done;
 
199
    ticket->enc_part.ciphertext.length = enclen;
 
200
    if (!(ticket->enc_part.ciphertext.data = malloc(enclen))) {
 
201
        code = ENOMEM;
 
202
        goto Done;
 
203
    }
 
204
    if ((code = krb5_c_encrypt(context, key, KRB5_KEYUSAGE_KDC_REP_TICKET,
 
205
                               0, data, &ticket->enc_part))) {
 
206
        free(ticket->enc_part.ciphertext.data);
 
207
        ticket->enc_part.ciphertext.data = 0;
 
208
    }
 
209
Done:
 
210
    if (data) {
 
211
        if (data->data)
 
212
            free(data->data);
 
213
        free(data);
 
214
    }
 
215
    return code;
 
216
}
 
217
#endif
 
218
 
187
219
#if defined(HAVE_KRB5_CREDS_KEYBLOCK)
188
220
 
189
221
#define get_cred_keydata(c) c->keyblock.contents
203
235
#if !defined(HAVE_KRB5_524_CONVERT_CREDS) && defined(HAVE_KRB524_CONVERT_CREDS_KDC)
204
236
#define krb5_524_convert_creds krb524_convert_creds_kdc
205
237
#elif !defined(HAVE_KRB5_524_CONVERT_CREDS) && !defined(HAVE_KRB524_CONVERT_CREDS_KDC)
206
 
#error "You must have one of krb5_524_convert_creds or krb524_convert_creds_kdc available"
207
 
#endif
208
 
 
209
 
#endif /* WINDOWS */
 
238
#define HAVE_NO_KRB5_524
 
239
#endif
 
240
 
 
241
#if USING_HEIMDAL
 
242
#define deref_keyblock_enctype(kb)              \
 
243
    ((kb)->keytype)
 
244
 
 
245
#define deref_entry_keyblock(entry)             \
 
246
    entry->keyblock
 
247
 
 
248
#define deref_session_key(creds)                \
 
249
    creds->session
 
250
 
 
251
#define deref_enc_tkt_addrs(tkt)                \
 
252
    tkt->caddr
 
253
 
 
254
#define deref_enc_length(enc)                   \
 
255
    ((enc)->cipher.length)
 
256
 
 
257
#define deref_enc_data(enc)                     \
 
258
    ((enc)->cipher.data)
 
259
 
 
260
#define krb5_free_keytab_entry_contents krb5_kt_free_entry
 
261
 
 
262
#else
 
263
#define deref_keyblock_enctype(kb)              \
 
264
    ((kb)->enctype)
 
265
 
 
266
#define deref_entry_keyblock(entry)             \
 
267
    entry->key
 
268
 
 
269
#define deref_session_key(creds)                \
 
270
    creds->keyblock
 
271
 
 
272
#define deref_enc_tkt_addrs(tkt)                \
 
273
    tkt->caddrs
 
274
 
 
275
#define deref_enc_length(enc)                   \
 
276
    ((enc)->ciphertext.length)
 
277
 
 
278
#define deref_enc_data(enc)                     \
 
279
    ((enc)->ciphertext.data)
 
280
 
 
281
#endif
 
282
 
 
283
#define deref_entry_enctype(entry)                      \
 
284
    deref_keyblock_enctype(&deref_entry_keyblock(entry))
210
285
 
211
286
/*
212
287
 * Provide a replacement for strerror if we don't have it
223
298
static int zsubs = FALSE;       /* Are we keeping track of zephyr subs? */
224
299
static int hosts = FALSE;       /* Are we keeping track of hosts? */
225
300
static int noprdb = FALSE;      /* Skip resolving name to id? */
226
 
static int linked = FALSE;  /* try for both AFS nodes */
227
 
static int afssetpag = FALSE; /* setpag for AFS */
 
301
static int linked = FALSE;      /* try for both AFS nodes */
 
302
static int afssetpag = FALSE;   /* setpag for AFS */
228
303
static int force = FALSE;       /* Bash identical tokens? */
229
304
static int do524 = FALSE;       /* Should we do 524 instead of rxkad2b? */
 
305
static char *keytab = NULL;     /* keytab for akimpersonate */
 
306
static char *client = NULL;     /* client principal for akimpersonate */
230
307
static linked_list zsublist;    /* List of zephyr subscriptions */
231
308
static linked_list hostlist;    /* List of host addresses */
232
309
static linked_list authedcells; /* List of cells already logged to */
266
343
    memset(local_cell, 0, sizeof(local_cell));
267
344
    memset((char *)cellconfig, 0, sizeof(*cellconfig));
268
345
 
269
 
#ifndef WINDOWS
270
 
 
271
346
    if (!(configdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH))) {
272
347
        fprintf(stderr, 
273
348
                "%s: can't get afs configuration (afsconf_Open(%s))\n",
294
369
 
295
370
    (void) afsconf_Close(configdir);
296
371
 
297
 
#else /* WINDOWS */
298
 
    /*
299
 
     * We'll try to mimic the GetCellInfo call here and fill in as much
300
 
     * of the afsconf_cell structure as we can.
301
 
     */
302
 
    if (cm_GetRootCellName(local_cell)) {
303
 
        fprintf(stderr, "%s: can't get local cellname\n", progname);
304
 
        exit(AKLOG_AFS);
305
 
    }
306
 
 
307
 
    if ((cell == NULL) || (cell[0] == 0))
308
 
        cell = local_cell;
309
 
 
310
 
    strcpy(cellconfig->name, cell);
311
 
 
312
 
    /* No way of figuring this out as far as I can tell */
313
 
    linkedcell[0] = '\0';
314
 
 
315
 
    /* Initialize server info */
316
 
    cellconfig->numServers = 0;
317
 
    cellconfig->hostName[0][0] = "\0";
318
 
 
319
 
    /*
320
 
     * Get servers of cell. cm_SearchCellFile_CallBack() gets call with
321
 
     * each server.
322
 
     */
323
 
    status = (int) cm_SearchCellFile(cell, NULL, &cm_SearchCellFile_CallBack,
324
 
                                     cellconfig /* rock */);
325
 
 
326
 
    switch(status) {
327
 
    case 0:
328
 
        break;
329
 
 
330
 
    case -1:
331
 
        fprintf(stderr, "%s: GetWindowsDirectory() failed.\n", progname);
332
 
        break;
333
 
 
334
 
    case -2:
335
 
        fprintf(stderr, "%s: Couldn't open afsdcells.ini for reading\n",
336
 
                progname);
337
 
        break;
338
 
 
339
 
    case -3:
340
 
        fprintf(stderr, "%s: Couldn't find any servers for cell %s\n",
341
 
                progname, cell);
342
 
        break;
343
 
 
344
 
    case -4:
345
 
        fprintf(stderr, "%s: Badly formatted line in afsdcells.ini (does not begin with a \">\" or contain \"#\"\n",
346
 
                progname);
347
 
        break;
348
 
 
349
 
    default:
350
 
        fprintf(stderr, "%s cm_SearchCellFile returned unknown error %d\n",
351
 
                status);
352
 
    }
353
 
 
354
 
    if (status) {
355
 
        exit(AKLOG_AFS);
356
 
    }
357
 
 
358
 
    status = AKLOG_SUCCESS;
359
 
 
360
 
    
361
 
#endif /* WINDOWS */
362
 
 
363
372
    return(status);
364
373
}
365
374
 
366
 
 
367
 
#ifdef WINDOWS
368
 
/*
369
 
 * Callback function for cm_SearchCellFile() in get_cellconfig() above.
370
 
 * This function gets called once for each server that is found for the cell.
371
 
 */
372
 
static long
373
 
cm_SearchCellFile_CallBack(void *rock /* cellconfig */,
374
 
                           struct sockaddr_in *addr, /* Not used */
375
 
                           char *server)
376
 
{
377
 
    struct afsconf_cell *cellconfig = rock;
378
 
 
379
 
 
380
 
    /*
381
 
     * Save server name and increment count of servers
382
 
     */
383
 
    strcpy(cellconfig->hostName[cellconfig->numServers++], server);
384
 
    
385
 
    return (long) 0;
386
 
}
387
 
 
388
 
    
389
 
#endif /* WINDOWS */
390
 
 
391
 
 
392
375
/* 
393
376
 * Log to a cell.  If the cell has already been logged to, return without
394
377
 * doing anything.  Otherwise, log to it and mark that it has been logged
400
383
    char username[BUFSIZ];      /* To hold client username structure */
401
384
    afs_int32 viceId;           /* AFS uid of user */
402
385
 
403
 
    char name[ANAME_SZ];        /* Name of afs key */
404
 
    char primary_instance[INST_SZ];     /* Instance of afs key */
405
 
    char secondary_instance[INST_SZ];   /* Backup instance to try */
406
 
    int try_secondary = 0;              /* Flag to indicate if we try second */
407
386
    char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
408
 
    char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
 
387
    char *realm_from_princ = 0 ;  /* Calculated realm data */
 
388
    char *realm_of_cell = 0;      /* Pointer to realm we're using */    
 
389
    int retry;                    /* round, and round we go ... */
 
390
    
409
391
    char local_cell[MAXCELLCHARS+1];
410
392
    char cell_to_use[MAXCELLCHARS+1]; /* Cell to authenticate to */
411
393
    static char lastcell[MAXCELLCHARS+1] = { 0 };
412
 
#ifndef WINDOWS
413
394
    static char confname[512] = { 0 };
414
 
#endif
415
395
    krb5_creds *v5cred = NULL;
416
396
    struct ktc_principal aserver;
417
397
    struct ktc_principal aclient;
418
398
    struct ktc_token atoken, btoken;
419
399
 
420
 
#ifdef ALLOW_REGISTER
421
 
    afs_int32 id;
422
 
#endif /* ALLOW_REGISTER */
423
 
 
424
 
    memset(name, 0, sizeof(name));
425
 
    memset(primary_instance, 0, sizeof(primary_instance));
426
 
    memset(secondary_instance, 0, sizeof(secondary_instance));
427
400
    memset(realm_of_user, 0, sizeof(realm_of_user));
428
 
    memset(realm_of_cell, 0, sizeof(realm_of_cell));
429
401
 
430
 
#ifndef WINDOWS
431
402
    if (confname[0] == '\0') {
432
403
        strncpy(confname, AFSDIR_CLIENT_ETC_DIRPATH, sizeof(confname));
433
404
        confname[sizeof(confname) - 2] = '\0';
434
405
    }
435
 
#endif /* WINDOWS */
436
406
 
437
407
    /* NULL or empty cell returns information on local cell */
438
408
    if ((status = get_cellconfig(cell, &ak_cellconfig,
483
453
                   cell_to_use, ak_cellconfig.hostName[0]);
484
454
        }
485
455
 
486
 
        /*
487
 
         * Find out which realm we're supposed to authenticate to.  If one
488
 
         * is not included, use the kerberos realm found in the credentials
489
 
         * cache.
490
 
         */
491
 
 
492
 
        if (realm && realm[0]) {
493
 
            strcpy(realm_of_cell, realm);
494
 
            if (dflag) {
495
 
                printf("We were told to authenticate to realm %s.\n", realm);
496
 
            }
497
 
        }
498
 
        else {
499
 
            char *realm = afs_realm_of_cell(context, &ak_cellconfig);
500
 
 
501
 
            if (!realm) {
502
 
                fprintf(stderr, 
503
 
                        "%s: Couldn't figure out realm for cell %s.\n",
504
 
                        progname, cell_to_use);
505
 
                exit(AKLOG_MISC);
506
 
            }
507
 
 
508
 
            strcpy(realm_of_cell, realm);
509
 
 
510
 
            if (dflag) {
511
 
                printf("We've deduced that we need to authenticate to"
512
 
                       " realm %s.\n", realm_of_cell);
513
 
            }
514
 
        }
515
 
 
516
 
        /* We use the afs.<cellname> convention here... 
517
 
         *
518
 
         * Doug Engert's original code had principals of the form:
519
 
         *
520
 
         * "afsx/cell@realm"
521
 
         *
522
 
         * in the KDC, so the name wouldn't conflict with DFS.  Since we're
523
 
         * not using DFS, I changed it just to look for the following
524
 
         * principals:
525
 
         *
526
 
         * afs/<cell>@<realm>
527
 
         * afs@<realm>
528
 
         *
529
 
         * Because people are transitioning from afs@realm to afs/cell,
530
 
         * we configure things so that if the first one isn't found, we
531
 
         * try the second one.  You can select which one you prefer with
532
 
         * a configure option.
533
 
         */
534
 
 
535
 
        strcpy(name, AFSKEY);
536
 
 
537
 
        if (AFS_TRY_FULL_PRINC || strcasecmp(cell_to_use, realm_of_cell) != 0) {
538
 
            strncpy(primary_instance, cell_to_use, sizeof(primary_instance));
539
 
            primary_instance[sizeof(primary_instance)-1] = '\0';
540
 
            if (strcasecmp(cell_to_use, realm_of_cell) == 0) {
541
 
                try_secondary = 1;
542
 
                secondary_instance[0] = '\0';
543
 
            }
544
 
        } else {
545
 
            primary_instance[0] = '\0';
546
 
            try_secondary = 1;
547
 
            strncpy(secondary_instance, cell_to_use,
548
 
                    sizeof(secondary_instance));
549
 
            secondary_instance[sizeof(secondary_instance)-1] = '\0';
550
 
        }
551
 
 
552
 
        /* 
553
 
         * Extract the session key from the ticket file and hand-frob an
554
 
         * afs style authenticator.
555
 
         */
556
 
 
557
 
        /*
558
 
         * Try to obtain AFS tickets.  Because there are two valid service
559
 
         * names, we will try both, but trying the more specific first.
560
 
         *
561
 
         *      afs/<cell>@<realm> i.e. allow for single name with "."
562
 
         *      afs@<realm>
563
 
         */
564
 
 
565
 
        if (dflag) {
566
 
            printf("Getting tickets: %s/%s@%s\n", name,
567
 
                   primary_instance, realm_of_cell);
568
 
        }
569
 
 
570
 
        status = get_credv5(context, name, primary_instance, realm_of_cell,
571
 
                            &v5cred);
572
 
 
573
 
        if (status == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || status == KRB5KRB_ERR_GENERIC) {
574
 
            if (try_secondary) {
575
 
                if (dflag) {
576
 
                    printf("Principal not found, trying alternate "
577
 
                           "service name: %s/%s@%s\n", name,
578
 
                            secondary_instance, realm_of_cell);
579
 
                }
580
 
                status = get_credv5(context, name, secondary_instance,
 
456
        if ((status = get_user_realm(context, realm_of_user))) {
 
457
            fprintf(stderr, "%s: Couldn't determine realm of user:)",
 
458
                    progname);
 
459
            afs_com_err(progname, status, " while getting realm");
 
460
            return(AKLOG_KERBEROS);
 
461
        }
 
462
 
 
463
        retry = 1;
 
464
        
 
465
        while(retry) {
 
466
            
 
467
            /* Cell on command line - use that one */
 
468
            if (realm && realm[0]) {
 
469
                realm_of_cell = realm;
 
470
                status = AKLOG_TRYAGAIN;
 
471
                if (dflag) {
 
472
                    printf("We were told to authenticate to realm %s.\n", 
 
473
                           realm);
 
474
                }
 
475
            } else {
 
476
                /* Initially, try using afs/cell@USERREALM */
 
477
                if (dflag) {
 
478
                    printf("Trying to authenticate to user's realm %s.\n",
 
479
                           realm_of_user);
 
480
                }
 
481
                
 
482
                realm_of_cell = realm_of_user;
 
483
                status = get_credv5(context, AFSKEY, cell_to_use, 
581
484
                                    realm_of_cell, &v5cred);
582
 
            }
583
 
        }
584
 
 
585
 
        if (status) {
 
485
            
 
486
                /* If that failed, try to determine the realm from the name of 
 
487
                 * one of the DB servers */
 
488
                if (TRYAGAIN(status)) {
 
489
                    realm_of_cell = afs_realm_of_cell(context, &ak_cellconfig, 
 
490
                                                      FALSE);
 
491
                    if (!realm_of_cell) {
 
492
                        fprintf(stderr, 
 
493
                                "%s: Couldn't figure out realm for cell %s.\n",
 
494
                                progname, cell_to_use);
 
495
                        exit(AKLOG_MISC);
 
496
                    }
 
497
 
 
498
                    if (dflag) {
 
499
                        if (realm_of_cell[0])
 
500
                            printf("We've deduced that we need to authenticate"
 
501
                                   " to realm %s.\n", realm_of_cell);
 
502
                    else
 
503
                        printf("We've deduced that we need to authenticate "
 
504
                               "using referrals.\n");
 
505
                    }
 
506
                }
 
507
            }
 
508
        
 
509
            if (TRYAGAIN(status)) {
 
510
                /* If we've got the full-princ-first option, or we're in a
 
511
                 * different realm from the cell - use the cell name as the
 
512
                 * instance */
 
513
                if (AFS_TRY_FULL_PRINC || 
 
514
                    strcasecmp(cell_to_use, realm_of_cell)!=0) {
 
515
                    status = get_credv5(context, AFSKEY, cell_to_use, 
 
516
                                        realm_of_cell, &v5cred);
 
517
 
 
518
                    /* If we failed & we've got an empty realm, then try 
 
519
                     * calling afs_realm_for_cell again. */
 
520
                    if (TRYAGAIN(status) && !realm_of_cell[0]) {
 
521
                        /* This time, get the realm by taking the domain 
 
522
                         * component of the db server and make it upper case */
 
523
                        realm_of_cell = afs_realm_of_cell(context, 
 
524
                                                          &ak_cellconfig, TRUE);
 
525
                        if (!realm_of_cell) {
 
526
                            fprintf(stderr,
 
527
                                    "%s: Couldn't figure out realm for cell "
 
528
                                    "%s.\n", progname, cell_to_use);
 
529
                            exit(AKLOG_MISC);
 
530
                        }
 
531
                        printf("We've deduced that we need to authenticate to"
 
532
                               " realm %s.\n", realm_of_cell);
 
533
                    }
 
534
                    status = get_credv5(context, AFSKEY, cell_to_use, 
 
535
                                        realm_of_cell, &v5cred);
 
536
                }
 
537
           
 
538
                /* If the realm and cell name match, then try without an 
 
539
                 * instance, but only if realm is non-empty */
 
540
                
 
541
                if (TRYAGAIN(status) && 
 
542
                    strcasecmp(cell_to_use, realm_of_cell) == 0) {
 
543
                    status = get_credv5(context, AFSKEY, NULL, 
 
544
                                        realm_of_cell, &v5cred);
 
545
                    if (!AFS_TRY_FULL_PRINC && TRYAGAIN(status)) {
 
546
                        status = get_credv5(context, AFSKEY, cell_to_use,
 
547
                                            realm_of_cell, &v5cred);
 
548
                    }
 
549
                }
 
550
            }
 
551
 
 
552
            /* Try to find a service principal for this cell.
 
553
             * Some broken MIT libraries return KRB5KRB_AP_ERR_MSG_TYPE upon 
 
554
             * the first attempt, so we try twice to be sure */
 
555
 
 
556
            if (status == KRB5KRB_AP_ERR_MSG_TYPE && retry == 1)
 
557
                retry++;
 
558
            else
 
559
                retry = 0;
 
560
        } 
 
561
        
 
562
        if (status != 0) {
586
563
            if (dflag) {
587
 
                printf("Kerberos error code returned by get_cred: %d\n",
588
 
                        status);
 
564
                printf("Kerberos error code returned by get_cred : %d\n",
 
565
                       status);
589
566
            }
590
567
            fprintf(stderr, "%s: Couldn't get %s AFS tickets:\n",
591
568
                    progname, cell_to_use);
592
 
                com_err(progname, status, "while getting AFS tickets");
 
569
            afs_com_err(progname, status, "while getting AFS tickets");
593
570
            return(AKLOG_KERBEROS);
594
571
        }
 
572
        
 
573
        /* If we've got a valid ticket, and we still don't know the realm name
 
574
         * try to figure it out from the contents of the ticket
 
575
         */
 
576
#if !defined(USING_HEIMDAL) && defined(HAVE_KRB5_DECODE_TICKET)
 
577
        if (strcmp(realm_of_cell, "") == 0) {
 
578
            krb5_error_code code;
 
579
            krb5_ticket *ticket;
 
580
 
 
581
            code = krb5_decode_ticket(&v5cred->ticket, &ticket);
 
582
 
 
583
            if (code != 0) {
 
584
                fprintf(stderr,
 
585
                        "%s: Couldn't decode ticket to determine realm for "
 
586
                        "cell %s.\n",
 
587
                        progname, cell_to_use);
 
588
            } else {
 
589
                int len = realm_len(context, ticket->server);
 
590
                /* This really shouldn't happen. */
 
591
                if (len > REALM_SZ-1)
 
592
                    len = REALM_SZ-1;
 
593
 
 
594
                realm_from_princ = (char *) malloc(sizeof(char) * (len+1));
 
595
                
 
596
                strncpy(realm_from_princ, realm_data(context, ticket->server), 
 
597
                        len);
 
598
                realm_from_princ[len] = 0;
 
599
                realm_of_cell = realm_from_princ;
 
600
                
 
601
                krb5_free_ticket(context, ticket);
 
602
            }
 
603
        }
 
604
#endif
595
605
 
596
606
        strncpy(aserver.name, AFSKEY, MAXKTCNAMELEN - 1);
597
607
        strncpy(aserver.instance, AFSINST, MAXKTCNAMELEN - 1);
633
643
                   get_cred_keylen(v5cred));
634
644
            atoken.ticketLen = v5cred->ticket.length;
635
645
            memcpy(atoken.ticket, v5cred->ticket.data, atoken.ticketLen);
 
646
#ifndef HAVE_NO_KRB5_524
636
647
        } else {
637
648
            CREDENTIALS cred;
638
649
 
642
653
            status = krb5_524_convert_creds(context, v5cred, &cred);
643
654
 
644
655
            if (status) {
645
 
                com_err(progname, status, "while converting tickets "
 
656
                afs_com_err(progname, status, "while converting tickets "
646
657
                        "to Kerberos V4 format");
647
658
                return(AKLOG_KERBEROS);
648
659
            }
667
678
            memcpy(&atoken.sessionKey, cred.session, 8);
668
679
            atoken.ticketLen = cred.ticket_st.length;
669
680
            memcpy(atoken.ticket, cred.ticket_st.dat, atoken.ticketLen);
 
681
#endif /* HAVE_NO_KRB5_524 */
670
682
        }
671
683
        
672
684
        if (!force &&
686
698
        noprdb = 1;
687
699
#endif
688
700
 
689
 
#ifndef WINDOWS
690
701
        if (noprdb) {
691
 
#endif
692
702
            if (dflag) {
693
703
                printf("Not resolving name %s to id (-noprdb set)\n",
694
704
                        username);
695
705
            }
696
 
#ifndef WINDOWS
697
706
        }
698
707
        else {
699
 
            if ((status = get_user_realm(context, realm_of_user))) {
700
 
                fprintf(stderr, "%s: Couldn't determine realm of user:)",
701
 
                        progname);
702
 
                com_err(progname, status, " while getting realm");
703
 
                return(AKLOG_KERBEROS);
704
 
            }
705
708
            if (strcmp(realm_of_user, realm_of_cell)) {
706
709
                strcat(username, "@");
707
710
                strcat(username, realm_of_user);
740
743
                 */
741
744
 
742
745
#ifdef ALLOW_REGISTER
743
 
        if (status == 0) {
744
 
            if (viceId != ANONYMOUSID) {
745
 
#else /* ALLOW_REGISTER */
746
 
            if ((status == 0) && (viceId != ANONYMOUSID))
747
 
#endif /* ALLOW_REGISTER */
748
 
                sprintf (username, "AFS ID %d", (int) viceId);
749
 
#ifdef ALLOW_REGISTER
750
 
            } else if (strcmp(realm_of_user, realm_of_cell) != 0) {
 
746
            if ((status == 0) && (viceId == ANONYMOUSID) &&
 
747
                (strcmp(realm_of_user, realm_of_cell) != 0)) {
751
748
                if (dflag) {
752
749
                    printf("doing first-time registration of %s "
753
750
                            "at %s\n", username, cell_to_use);
754
751
                }
755
 
                id = 0;
 
752
                viceId = 0;
756
753
                strncpy(aclient.name, username, MAXKTCNAMELEN - 1);
757
754
                strcpy(aclient.instance, "");
758
755
                strncpy(aclient.cell, realm_of_user, MAXKTCREALMLEN - 1);
773
770
                    printf("Error %d\n", status);
774
771
                }
775
772
 
776
 
                if ((status = pr_CreateUser(username, &id))) {
 
773
                if ((status = pr_CreateUser(username, &viceId))) {
777
774
                    fprintf(stderr, "%s: %s so unable to create remote PTS "
778
775
                            "user %s in cell %s (status: %d).\n", progname,
779
 
                            error_message(status), username, cell_to_use,
 
776
                            afs_error_message(status), username, cell_to_use,
780
777
                            status);
 
778
                    viceId = ANONYMOUSID;
781
779
                } else {
782
 
                    printf("created cross-cell entry for %s at %s\n",
783
 
                           username, cell_to_use);
784
 
                    sprintf(username, "AFS ID %d", (int) id);
 
780
                    printf("created cross-cell entry for %s (Id %d) at %s\n",
 
781
                           username, viceId, cell_to_use);
785
782
                }
786
783
            }
787
 
        }
788
784
#endif /* ALLOW_REGISTER */
789
785
 
 
786
            if ((status == 0) && (viceId != ANONYMOUSID)) {
 
787
                sprintf(username, "AFS ID %d", (int) viceId);
 
788
            }
790
789
        }
791
 
#endif /* !WINDOWS */
792
790
 
793
791
        if (dflag) {
794
792
            fprintf(stdout, "Set username to %s\n", username);
806
804
            printf("Setting tokens. %s / %s @ %s \n",
807
805
                    aclient.name, aclient.instance, aclient.cell );
808
806
        }
 
807
#ifndef AFS_AIX51_ENV
809
808
        /* on AIX 4.1.4 with AFS 3.4a+ if a write is not done before 
810
809
         * this routine, it will not add the token. It is not clear what 
811
 
         * is going on here! So we will do the following operation
 
810
         * is going on here! So we will do the following operation.
 
811
         * On AIX 5, it causes the parent program to die, so we won't.
812
812
         */
813
813
        write(2,"",0); /* dummy write */
814
 
#ifndef WINDOWS
 
814
#endif
815
815
        if ((status = ktc_SetToken(&aserver, &atoken, &aclient, afssetpag))) {
816
816
            fprintf(stderr, 
817
817
                    "%s: unable to obtain tokens for cell %s (status: %d).\n",
818
818
                    progname, cell_to_use, status);
819
819
            status = AKLOG_TOKEN;
820
820
        }
821
 
#else /* WINDOWS */
822
 
        /* Note switched 2nd and 3rd args */
823
 
        if ((status = ktc_SetToken(&aserver, &atoken, &aclient, afssetpag))) {
824
 
            switch(status) {
825
 
            case KTC_INVAL:
826
 
                fprintf(stderr, "%s: Bad ticket length", progname);
827
 
                break;
828
 
            case KTC_PIOCTLFAIL:
829
 
                fprintf(stderr, "%s: Unknown error contacting AFS service",
830
 
                        progname);
831
 
                break;
832
 
            case KTC_NOCELL:
833
 
                fprintf(stderr, "%s: Cell name (%s) not recognized by AFS service",
834
 
                        progname, realm_of_cell);
835
 
                break;
836
 
            case KTC_NOCM:
837
 
                fprintf(stderr, "%s: AFS service is unavailable", progname);
838
 
                break;
839
 
            default:
840
 
                fprintf(stderr, "%s: Undocumented error (%d) contacting AFS service", progname, status);
841
 
                break;  
842
 
            }
843
 
            status = AKLOG_TOKEN;           
844
 
        }
845
 
#endif /* !WINDOWS */
846
821
    }
847
822
    else
848
823
        if (dflag) {
852
827
    return(status);
853
828
}
854
829
 
855
 
#ifndef WINDOWS /* struct ViceIoctl missing */
856
 
 
857
830
static int get_afs_mountpoint(char *file, char *mountpoint, int size)
858
831
{
859
832
#ifdef AFS_SUN_ENV
950
923
            ? elast_comp - last_comp : strlen(last_comp);
951
924
        strncat(pathtocheck, last_comp, len);
952
925
        memset(linkbuf, 0, sizeof(linkbuf));
953
 
        if (link = (readlink(pathtocheck, linkbuf, 
954
 
                                    sizeof(linkbuf)) > 0)) {
 
926
        if ((link = (readlink(pathtocheck, linkbuf, 
 
927
                                    sizeof(linkbuf)) > 0))) {
955
928
            if (++symlinkcount > MAXSYMLINKS) {
956
929
                fprintf(stderr, "%s: %s\n", progname, strerror(ELOOP));
957
930
                exit(AKLOG_BADPATH);
995
968
    return(pathtocheck);
996
969
}
997
970
 
998
 
#endif /* WINDOWS */
999
 
 
1000
971
#if 0
1001
972
/*****************************************/
1002
973
int dee_gettokens()
1027
998
/*****************************************/
1028
999
#endif
1029
1000
 
1030
 
#ifndef WINDOWS /* struct ViceIoctl missing */
1031
 
 
1032
1001
static void add_hosts(char *file)
1033
1002
{
1034
1003
#ifdef AFS_SUN_ENV
1088
1057
    }
1089
1058
}
1090
1059
 
1091
 
#endif /* WINDOWS */
1092
 
 
1093
 
#ifndef WINDOWS /* next_path(), get_afs_mountpoint() */
1094
 
 
1095
1060
/*
1096
1061
 * This routine descends through a path to a directory, logging to 
1097
1062
 * every cell it encounters along the way.
1179
1144
    return(status);
1180
1145
}
1181
1146
 
1182
 
#endif /* WINDOWS */
1183
 
 
1184
1147
 
1185
1148
/* Print usage message and exit */
1186
1149
static void usage(void)
1189
1152
            "[-d] [[-cell | -c] cell [-k krb_realm]] ",
1190
1153
            "[[-p | -path] pathname]\n",
1191
1154
            "    [-zsubs] [-hosts] [-noauth] [-noprdb] [-force] [-setpag] \n"
1192
 
            "    [-linked] [-524]\n");
 
1155
                "    [-linked]"
 
1156
#ifndef HAVE_NO_KRB5_524
 
1157
                " [-524]"
 
1158
#endif
 
1159
                "\n");
1193
1160
    fprintf(stderr, "    -d gives debugging information.\n");
1194
1161
    fprintf(stderr, "    krb_realm is the kerberos realm of a cell.\n");
1195
1162
    fprintf(stderr, "    pathname is the name of a directory to which ");
1201
1168
    fprintf(stderr, "    -force means replace identical tickets. \n");
1202
1169
    fprintf(stderr, "    -linked means if AFS node is linked, try both. \n");
1203
1170
    fprintf(stderr, "    -setpag set the AFS process authentication group.\n");
 
1171
#ifndef HAVE_NO_KRB5_524
1204
1172
    fprintf(stderr, "    -524 means use the 524 converter instead of V5 directly\n");
 
1173
#endif
1205
1174
    fprintf(stderr, "    No commandline arguments means ");
1206
1175
    fprintf(stderr, "authenticate to the local cell.\n");
1207
1176
    fprintf(stderr, "\n");
1251
1220
        progname = argv[0];
1252
1221
 
1253
1222
    krb5_init_context(&context);
1254
 
#ifndef WINDOWS
1255
 
        initialize_ktc_error_table ();
1256
 
#endif
 
1223
    initialize_ktc_error_table ();
1257
1224
 
1258
1225
    /* Initialize list of cells to which we have authenticated */
1259
1226
    (void)ll_init(&authedcells);
1274
1241
                linked++;
1275
1242
        else if (strcmp(argv[i], "-force") == 0)
1276
1243
            force++;
 
1244
#ifndef HAVE_NO_KRB5_524
1277
1245
        else if (strcmp(argv[i], "-524") == 0)
1278
1246
            do524++;
 
1247
#endif
1279
1248
    else if (strcmp(argv[i], "-setpag") == 0)
1280
1249
            afssetpag++;
1281
1250
        else if (((strcmp(argv[i], "-cell") == 0) ||
1286
1255
            }
1287
1256
            else
1288
1257
                usage();
 
1258
        else if ((strcmp(argv[i], "-keytab") == 0))
 
1259
            if (++i < argc) {
 
1260
                keytab = argv[i];
 
1261
            }
 
1262
            else
 
1263
                usage();
 
1264
        else if ((strcmp(argv[i], "-principal") == 0))
 
1265
            if (++i < argc) {
 
1266
                client = argv[i];
 
1267
            }
 
1268
            else
 
1269
                usage();
1289
1270
        else if (((strcmp(argv[i], "-path") == 0) ||
1290
1271
                  (strcmp(argv[i], "-p") == 0)) && !cmode)
1291
 
#ifndef WINDOWS
1292
1272
            if (++i < argc) {
1293
1273
                pmode++;
1294
1274
                strcpy(path, argv[i]);
1295
1275
            }
1296
1276
            else
1297
1277
                usage();
1298
 
#else /* WINDOWS */
1299
 
        {
1300
 
            fprintf(stderr, "%s: path mode not supported.\n", progname);
1301
 
            exit(AKLOG_MISC);
1302
 
        }
1303
 
#endif /* WINDOWS */
1304
1278
            
1305
1279
        else if (argv[i][0] == '-')
1306
1280
            usage();
1307
1281
        else if (!pmode && !cmode) {
1308
1282
            if (strchr(argv[i], DIR) || (strcmp(argv[i], ".") == 0) ||
1309
1283
                (strcmp(argv[i], "..") == 0)) {
1310
 
#ifndef WINDOWS
1311
1284
                pmode++;
1312
1285
                strcpy(path, argv[i]);
1313
 
#else /* WINDOWS */
1314
 
                fprintf(stderr, "%s: path mode not supported.\n", progname);
1315
 
                exit(AKLOG_MISC);
1316
 
#endif /* WINDOWS */
1317
1286
            }
1318
1287
            else { 
1319
1288
                cmode++;
1354
1323
            memset(cell, 0, sizeof(cell));
1355
1324
            memset(realm, 0, sizeof(realm));
1356
1325
        }
1357
 
#ifndef WINDOWS
1358
1326
        else if (pmode) {
1359
1327
            /* Add this path to list of paths */
1360
1328
            if ((cur_node = ll_add_node(&paths, ll_tail))) {
1375
1343
            pmode = FALSE;
1376
1344
            memset(path, 0, sizeof(path));
1377
1345
        }
1378
 
#endif /* WINDOWS */
1379
1346
    }
1380
1347
 
1381
1348
    /*
1427
1394
                                status = auth_to_cell(context, linkedcell2, NULL);
1428
1395
                }
1429
1396
 
1430
 
#ifndef WINDOWS
1431
1397
                /*
1432
1398
                 * Local hack - if the person has a file in their home
1433
1399
                 * directory called ".xlog", read that for a list of
1468
1434
                        }
1469
1435
                    }
1470
1436
                }
1471
 
#endif /* WINDOWS */
1472
1437
        }
1473
1438
    else {
1474
1439
        /* Log to all cells in the cells list first */
1490
1455
                }
1491
1456
        }
1492
1457
        
1493
 
#ifndef WINDOWS
1494
1458
        /* Then, log to all paths in the paths list */
1495
1459
        for (cur_node = paths.first; cur_node; cur_node = cur_node->next) {
1496
1460
            if ((status = auth_to_path(context, cur_node->data)))
1497
1461
                somethingswrong++;
1498
1462
        }
1499
 
#endif /* WINDOWS */
1500
1463
        
1501
1464
        /* 
1502
1465
         * If only one thing was logged to, we'll return the status 
1522
1485
    exit(status);
1523
1486
}
1524
1487
 
1525
 
#ifndef HAVE_ADD_TO_ERROR_TABLE
1526
 
 
1527
 
#define error_table error_table_compat
1528
 
#include <afs/error_table.h>
1529
 
#undef error_table
1530
 
 
1531
 
#ifndef HAVE_ADD_ERROR_TABLE
1532
 
void add_error_table (const struct error_table *);
1533
 
#endif /* !HAVE_ADD_ERROR_TABLE */
1534
 
 
1535
 
void
1536
 
add_to_error_table(struct et_list *new_table)
1537
 
{
1538
 
        add_error_table((struct error_table *) new_table->table);
1539
 
}
1540
 
#endif /* HAVE_ADD_TO_ERROR_TABLE */
1541
 
 
1542
1488
static int isdir(char *path, unsigned char *val)
1543
1489
{
1544
1490
    struct stat statbuf;
1554
1500
    }  
1555
1501
}
1556
1502
 
 
1503
static krb5_error_code get_credv5_akimpersonate(krb5_context context,
 
1504
                                                char* keytab,
 
1505
                                                krb5_principal service_principal,
 
1506
                                                krb5_principal client_principal,
 
1507
                                                time_t starttime,
 
1508
                                                time_t endtime,
 
1509
                                                int *allowed_enctypes,
 
1510
                                                int *paddress,
 
1511
                                                krb5_creds** out_creds /* out */ )
 
1512
{
 
1513
#if defined(USING_HEIMDAL) || (defined(HAVE_ENCODE_KRB5_ENC_TKT) && defined(HAVE_ENCODE_KRB5_TICKET) && defined(HAVE_KRB5_C_ENCRYPT))
 
1514
    krb5_error_code code;
 
1515
    krb5_keytab kt = 0;
 
1516
    krb5_kt_cursor cursor[1];
 
1517
    krb5_keytab_entry entry[1];
 
1518
    krb5_ccache cc = 0;
 
1519
    krb5_creds *creds = 0;
 
1520
    krb5_enctype enctype;
 
1521
    krb5_kvno kvno;
 
1522
    krb5_keyblock session_key[1];
 
1523
#if USING_HEIMDAL
 
1524
    Ticket ticket_reply[1];
 
1525
    EncTicketPart enc_tkt_reply[1];
 
1526
    krb5_address address[30];
 
1527
    krb5_addresses faddr[1];
 
1528
    int temp_vno[1];
 
1529
    time_t temp_time[2];
 
1530
#else
 
1531
    krb5_ticket ticket_reply[1];
 
1532
    krb5_enc_tkt_part enc_tkt_reply[1];
 
1533
    krb5_address address[30], *faddr[30];
 
1534
#endif
 
1535
    krb5_data * temp;
 
1536
    int i;
 
1537
    static int any_enctype[] = {0};
 
1538
    *out_creds = 0;
 
1539
    if (!(creds = malloc(sizeof *creds))) {
 
1540
        code = ENOMEM;
 
1541
        goto cleanup;
 
1542
    }
 
1543
    if (!allowed_enctypes)
 
1544
        allowed_enctypes = any_enctype;
 
1545
 
 
1546
    cc = 0;
 
1547
    enctype = 0; /* AKIMPERSONATE_IGNORE_ENCTYPE */
 
1548
    kvno = 0; /* AKIMPERSONATE_IGNORE_VNO */
 
1549
    memset((char*)creds, 0, sizeof *creds);
 
1550
    memset((char*)entry, 0, sizeof *entry);
 
1551
    memset((char*)session_key, 0, sizeof *session_key);
 
1552
    memset((char*)ticket_reply, 0, sizeof *ticket_reply);
 
1553
    memset((char*)enc_tkt_reply, 0, sizeof *enc_tkt_reply);
 
1554
    code = krb5_kt_resolve(context, keytab, &kt);
 
1555
    if (code) {
 
1556
        if (keytab)
 
1557
            afs_com_err(progname, code, "while resolving keytab %s", keytab);
 
1558
        else
 
1559
            afs_com_err(progname, code, "while resolving default keytab");
 
1560
        goto cleanup;
 
1561
    }
 
1562
 
 
1563
    if (service_principal) {
 
1564
        for (i = 0; (enctype = allowed_enctypes[i]) || !i; ++i) {
 
1565
            code = krb5_kt_get_entry(context,
 
1566
                                     kt,
 
1567
                                     service_principal,
 
1568
                                     kvno,
 
1569
                                     enctype,
 
1570
                                     entry);
 
1571
            if (!code) {
 
1572
                if (allowed_enctypes[i])
 
1573
                    deref_keyblock_enctype(session_key) = allowed_enctypes[i];
 
1574
                break;
 
1575
            }
 
1576
        }
 
1577
        if (code) {
 
1578
            afs_com_err(progname, code,"while scanning keytab entries");
 
1579
            goto cleanup;
 
1580
        }
 
1581
    } else {
 
1582
        krb5_keytab_entry new[1];
 
1583
        int best = -1;
 
1584
        memset(new, 0, sizeof *new);
 
1585
        if ((code == krb5_kt_start_seq_get(context, kt, cursor))) {
 
1586
            afs_com_err(progname, code, "while starting keytab scan");
 
1587
            goto cleanup;
 
1588
        }
 
1589
        while (!(code = krb5_kt_next_entry(context, kt, new, cursor))) {
 
1590
            for (i = 0;
 
1591
                    allowed_enctypes[i] && allowed_enctypes[i]
 
1592
                     != deref_entry_enctype(new); ++i)
 
1593
                ;
 
1594
            if ((!i || allowed_enctypes[i]) &&
 
1595
                (best < 0 || best > i)) {
 
1596
                krb5_free_keytab_entry_contents(context, entry);
 
1597
                *entry = *new;
 
1598
                memset(new, 0, sizeof *new);
 
1599
            } else krb5_free_keytab_entry_contents(context, new);
 
1600
        }
 
1601
        if ((i = krb5_kt_end_seq_get(context, kt, cursor))) {
 
1602
            afs_com_err(progname, i, "while ending keytab scan");
 
1603
            code = i;
 
1604
            goto cleanup;
 
1605
        }
 
1606
        if (best < 0) {
 
1607
            afs_com_err(progname, code, "while scanning keytab");
 
1608
            goto cleanup;
 
1609
        }
 
1610
        deref_keyblock_enctype(session_key) = deref_entry_enctype(entry);
 
1611
    }
 
1612
 
 
1613
    /* Make Ticket */
 
1614
 
 
1615
#if USING_HEIMDAL
 
1616
    if ((code = krb5_generate_random_keyblock(context,
 
1617
                                              deref_keyblock_enctype(session_key), session_key))) {
 
1618
        afs_com_err(progname, code, "while making session key");
 
1619
        goto cleanup;
 
1620
    }
 
1621
    enc_tkt_reply->flags.initial = 1;
 
1622
    enc_tkt_reply->transited.tr_type = DOMAIN_X500_COMPRESS;
 
1623
    enc_tkt_reply->cname = client_principal->name;
 
1624
    enc_tkt_reply->crealm = client_principal->realm;
 
1625
    enc_tkt_reply->key = *session_key;
 
1626
    {
 
1627
        static krb5_data empty_string;
 
1628
        enc_tkt_reply->transited.contents = empty_string;
 
1629
    }
 
1630
    enc_tkt_reply->authtime = starttime;
 
1631
    enc_tkt_reply->starttime = temp_time;
 
1632
    *enc_tkt_reply->starttime = starttime;
 
1633
#if 0
 
1634
    enc_tkt_reply->renew_till = temp_time + 1;
 
1635
    *enc_tkt_reply->renew_till = endtime;
 
1636
#endif
 
1637
    enc_tkt_reply->endtime = endtime;
 
1638
#else
 
1639
    if ((code = krb5_c_make_random_key(context,
 
1640
                                       deref_keyblock_enctype(session_key), session_key))) {
 
1641
        afs_com_err(progname, code, "while making session key");
 
1642
        goto cleanup;
 
1643
    }
 
1644
    enc_tkt_reply->magic = KV5M_ENC_TKT_PART;
 
1645
#define DATACAST        (unsigned char *)
 
1646
    enc_tkt_reply->flags |= TKT_FLG_INITIAL;
 
1647
    enc_tkt_reply->transited.tr_type = KRB5_DOMAIN_X500_COMPRESS;
 
1648
    enc_tkt_reply->session = session_key;
 
1649
    enc_tkt_reply->client = client_principal;
 
1650
    {
 
1651
        static krb5_data empty_string;
 
1652
        enc_tkt_reply->transited.tr_contents = empty_string;
 
1653
    }
 
1654
    enc_tkt_reply->times.authtime = starttime;
 
1655
    enc_tkt_reply->times.starttime = starttime; /* krb524init needs this */
 
1656
    enc_tkt_reply->times.endtime = endtime;
 
1657
#endif  /* USING_HEIMDAL */
 
1658
    /* NB:  We will discard address for now--ignoring caddr field               
 
1659
       in any case.  MIT branch does what it always did. */
 
1660
 
 
1661
    if (paddress && *paddress) {
 
1662
        deref_enc_tkt_addrs(enc_tkt_reply) = faddr;
 
1663
#if USING_HEIMDAL
 
1664
        faddr->len = 0;
 
1665
        faddr->val = address;
 
1666
#endif
 
1667
        for (i = 0; paddress[i]; ++i) {
 
1668
#if USING_HEIMDAL
 
1669
            address[i].addr_type = KRB5_ADDRESS_INET;
 
1670
            address[i].address.data = (void*)(paddress+i);
 
1671
            address[i].address.length = sizeof(paddress[i]);
 
1672
#else
 
1673
#if !USING_SSL
 
1674
            address[i].magic = KV5M_ADDRESS;
 
1675
            address[i].addrtype = ADDRTYPE_INET;
 
1676
#else
 
1677
            address[i].addrtype = AF_INET;
 
1678
#endif
 
1679
            address[i].contents = (void*)(paddress+i);
 
1680
            address[i].length = sizeof(int);
 
1681
            faddr[i] = address+i;
 
1682
#endif
 
1683
        }
 
1684
#if USING_HEIMDAL
 
1685
        faddr->len = i;
 
1686
#else
 
1687
        faddr[i] = 0;
 
1688
#endif
 
1689
    }
 
1690
 
 
1691
#if USING_HEIMDAL
 
1692
    ticket_reply->sname = service_principal->name;
 
1693
    ticket_reply->realm = service_principal->realm;
 
1694
 
 
1695
    { /* crypto block */
 
1696
        krb5_crypto crypto = 0;
 
1697
        unsigned char *buf = 0;
 
1698
        size_t buf_size, buf_len;
 
1699
        char *what;
 
1700
 
 
1701
        ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size,
 
1702
                           enc_tkt_reply, &buf_len, code);
 
1703
        if(code) {
 
1704
            afs_com_err(progname, code, "while encoding ticket");
 
1705
            goto cleanup;
 
1706
        }
 
1707
 
 
1708
        if(buf_len != buf_size) {
 
1709
            afs_com_err(progname, code,
 
1710
                    "%d != %d while encoding ticket (internal ASN.1 encoder error",
 
1711
                    buf_len, buf_size);
 
1712
            goto cleanup;
 
1713
        }
 
1714
        what = "krb5_crypto_init";
 
1715
        code = krb5_crypto_init(context,
 
1716
                                &deref_entry_keyblock(entry),
 
1717
                                deref_entry_enctype(entry),
 
1718
                                &crypto);
 
1719
        if(!code) {
 
1720
            what = "krb5_encrypt";
 
1721
            code = krb5_encrypt_EncryptedData(context, crypto, KRB5_KU_TICKET,
 
1722
                                              buf, buf_len, entry->vno, &(ticket_reply->enc_part));
 
1723
        }
 
1724
        if (buf) free(buf);
 
1725
        if (crypto) krb5_crypto_destroy(context, crypto);
 
1726
        if(code) {
 
1727
            afs_com_err(progname, code, "while %s", what);
 
1728
            goto cleanup;
 
1729
        }
 
1730
    } /* crypto block */
 
1731
    ticket_reply->enc_part.etype = deref_entry_enctype(entry);
 
1732
    ticket_reply->enc_part.kvno = temp_vno;
 
1733
    *ticket_reply->enc_part.kvno = entry->vno;
 
1734
    ticket_reply->tkt_vno = 5;
 
1735
#else
 
1736
    ticket_reply->server = service_principal;
 
1737
    ticket_reply->enc_part2 = enc_tkt_reply;
 
1738
    if ((code = krb5_encrypt_tkt_part(context, &deref_entry_keyblock(entry), ticket_reply))) {
 
1739
        afs_com_err(progname, code, "while making ticket");
 
1740
        goto cleanup;
 
1741
    }
 
1742
    ticket_reply->enc_part.kvno = entry->vno;
 
1743
#endif
 
1744
 
 
1745
    /* Construct Creds */
 
1746
 
 
1747
    if ((code = krb5_copy_principal(context, service_principal,
 
1748
                                    &creds->server))) {
 
1749
        afs_com_err(progname, code, "while copying service principal");
 
1750
        goto cleanup;
 
1751
    }
 
1752
    if ((code = krb5_copy_principal(context, client_principal,
 
1753
                                    &creds->client))) {
 
1754
        afs_com_err(progname, code, "while copying client principal");
 
1755
        goto cleanup;
 
1756
    }
 
1757
    if ((code = krb5_copy_keyblock_contents(context, session_key,
 
1758
                                            &deref_session_key(creds)))) {
 
1759
        afs_com_err(progname, code, "while copying session key");
 
1760
        goto cleanup;
 
1761
    }
 
1762
 
 
1763
#if USING_HEIMDAL
 
1764
    creds->times.authtime = enc_tkt_reply->authtime;
 
1765
    creds->times.starttime = *(enc_tkt_reply->starttime);
 
1766
    creds->times.endtime = enc_tkt_reply->endtime;
 
1767
    creds->times.renew_till = 0; /* *(enc_tkt_reply->renew_till) */
 
1768
    creds->flags.b = enc_tkt_reply->flags;
 
1769
#else
 
1770
    creds->times = enc_tkt_reply->times;
 
1771
    creds->ticket_flags = enc_tkt_reply->flags;
 
1772
#endif
 
1773
    if (!deref_enc_tkt_addrs(enc_tkt_reply))
 
1774
        ;
 
1775
    else if ((code = krb5_copy_addresses(context,
 
1776
                                         deref_enc_tkt_addrs(enc_tkt_reply), &creds->addresses))) {
 
1777
        afs_com_err(progname, code, "while copying addresses");
 
1778
        goto cleanup;
 
1779
    }
 
1780
 
 
1781
#if USING_HEIMDAL
 
1782
    {
 
1783
        size_t creds_tkt_len;
 
1784
        ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length,
 
1785
                           ticket_reply, &creds_tkt_len, code);
 
1786
        if(code) {
 
1787
            afs_com_err(progname, code, "while encoding ticket");
 
1788
            goto cleanup;
 
1789
        }
 
1790
    }
 
1791
#else
 
1792
    if ((code = encode_krb5_ticket(ticket_reply, &temp))) {
 
1793
        afs_com_err(progname, code, "while encoding ticket");
 
1794
        goto cleanup;
 
1795
    }
 
1796
    creds->ticket = *temp;
 
1797
    free(temp);
 
1798
#endif
 
1799
    /* return creds */
 
1800
    *out_creds = creds;
 
1801
    creds = 0;
 
1802
cleanup:
 
1803
    if (deref_enc_data(&ticket_reply->enc_part))
 
1804
        free(deref_enc_data(&ticket_reply->enc_part));
 
1805
    krb5_free_keytab_entry_contents(context, entry);
 
1806
    if (client_principal)
 
1807
        krb5_free_principal(context, client_principal);
 
1808
    if (service_principal)
 
1809
        krb5_free_principal(context, service_principal);
 
1810
    if (cc)
 
1811
        krb5_cc_close(context, cc);
 
1812
    if (kt)
 
1813
        krb5_kt_close(context, kt);
 
1814
    if (creds) krb5_free_creds(context, creds);
 
1815
    krb5_free_keyblock_contents(context, session_key);
 
1816
out:
 
1817
    return code;
 
1818
#else
 
1819
    return -1;
 
1820
#endif
 
1821
}
 
1822
 
 
1823
 
1557
1824
static krb5_error_code get_credv5(krb5_context context, 
1558
 
                        char *name, char *inst, char *realm,
1559
 
                        krb5_creds **creds)
 
1825
                                  char *name, char *inst, char *realm,
 
1826
                                  krb5_creds **creds)
1560
1827
{
1561
1828
    krb5_creds increds;
1562
1829
    krb5_error_code r;
1563
1830
    static krb5_principal client_principal = 0;
1564
1831
 
 
1832
    if (dflag) {
 
1833
        printf("Getting tickets: %s%s%s@%s\n", name, (inst && inst[0])
 
1834
               ? "/" : "", inst ? inst : "", realm);
 
1835
    }
 
1836
    
1565
1837
    memset((char *)&increds, 0, sizeof(increds));
1566
1838
/* ANL - instance may be ptr to a null string. Pass null then */
1567
1839
    if ((r = krb5_build_principal(context, &increds.server,
1568
 
                     strlen(realm), realm,
1569
 
                     name,
1570
 
           (inst && strlen(inst)) ? inst : (void *) NULL,
1571
 
                     (void *) NULL))) {
 
1840
                                  strlen(realm), realm,
 
1841
                                  name,
 
1842
                                  (inst && strlen(inst)) ? inst : (void *) NULL,
 
1843
                                  (void *) NULL))) {
1572
1844
        return r;
1573
1845
    }
 
1846
    
1574
1847
 
1575
1848
    if (!_krb425_ccache) {
1576
1849
        r = krb5_cc_default(context, &_krb425_ccache);
1578
1851
            return r;
1579
1852
    }
1580
1853
    if (!client_principal) {
1581
 
        r = krb5_cc_get_principal(context, _krb425_ccache, &client_principal);
 
1854
        if (client) {
 
1855
            r = krb5_parse_name(context, client,  &client_principal);
 
1856
        } else {
 
1857
            r = krb5_cc_get_principal(context, _krb425_ccache, &client_principal);
 
1858
        }
1582
1859
        if (r)
1583
1860
            return r;
1584
1861
    }
1585
 
 
 
1862
    
1586
1863
    increds.client = client_principal;
1587
1864
    increds.times.endtime = 0;
1588
 
        /* Ask for DES since that is what V4 understands */
 
1865
    /* Ask for DES since that is what V4 understands */
1589
1866
    get_creds_enctype((&increds)) = ENCTYPE_DES_CBC_CRC;
1590
 
 
1591
 
    r = krb5_get_credentials(context, 0, _krb425_ccache, &increds, creds);
1592
 
 
 
1867
    
 
1868
    if (keytab) {
 
1869
        int allowed_enctypes[] = {
 
1870
            ENCTYPE_DES_CBC_CRC, 0
 
1871
        };
 
1872
 
 
1873
        r = get_credv5_akimpersonate(context,
 
1874
                                     keytab,
 
1875
                                     increds.server,
 
1876
                                     increds.client,
 
1877
                                     300, ((~0U)>>1),
 
1878
                                     allowed_enctypes,
 
1879
                                     0 /* paddress */,
 
1880
                                     creds /* out */);
 
1881
    } else {
 
1882
        r = krb5_get_credentials(context, 0, _krb425_ccache, &increds, creds);
 
1883
    }    
1593
1884
    return r;
1594
1885
}
1595
1886
 
1598
1889
{
1599
1890
    static krb5_principal client_principal = 0;
1600
1891
    int i;
 
1892
    krb5_error_code r = 0;
1601
1893
 
1602
1894
    if (!_krb425_ccache)
1603
1895
        krb5_cc_default(context, &_krb425_ccache);
1604
 
    if (!client_principal)
1605
 
        krb5_cc_get_principal(context, _krb425_ccache, &client_principal);
 
1896
    if (!client_principal) {
 
1897
        if (client) {
 
1898
            r = krb5_parse_name(context, client,  &client_principal);
 
1899
        } else {
 
1900
            r = krb5_cc_get_principal(context, _krb425_ccache, &client_principal);
 
1901
        }
 
1902
        if (r)
 
1903
            return r;
 
1904
    }
1606
1905
 
1607
1906
    i = realm_len(context, client_principal);
1608
1907
    if (i > REALM_SZ-1) i = REALM_SZ-1;
1609
1908
    strncpy(realm,realm_data(context, client_principal), i);
1610
1909
    realm[i] = 0;
1611
1910
 
1612
 
    return(0);
 
1911
    return(r);
1613
1912
}