~ubuntu-branches/ubuntu/karmic/openafs/karmic-updates

« back to all changes in this revision

Viewing changes to src/aklog/klog.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
/*
 
2
 * Copyright 2000, International Business Machines Corporation and others.
 
3
 * All Rights Reserved.
 
4
 * 
 
5
 * This software has been released under the terms of the IBM Public
 
6
 * License.  For details, see the LICENSE file in the top-level source
 
7
 * directory or online at http://www.openafs.org/dl/license10.html
 
8
 */
 
9
 
 
10
#include <afsconfig.h>
 
11
#include <afs/param.h>
 
12
 
 
13
#include <afs/stds.h>
 
14
#include <sys/types.h>
 
15
#include <rx/xdr.h>
 
16
#ifdef  AFS_AIX32_ENV
 
17
#include <signal.h>
 
18
#endif
 
19
#ifdef HAVE_STRING_H
 
20
#include <string.h>
 
21
#else
 
22
#ifdef HAVE_STRINGS_H
 
23
#include <strings.h>
 
24
#endif
 
25
#endif
 
26
#include <errno.h>
 
27
 
 
28
#include <lock.h>
 
29
#include <ubik.h>
 
30
 
 
31
#include <stdio.h>
 
32
#include <pwd.h>
 
33
#include <afs/com_err.h>
 
34
#include <afs/auth.h>
 
35
#include <afs/afsutil.h>
 
36
#include <afs/cellconfig.h>
 
37
#ifdef AFS_RXK5
 
38
#include "rxk5_utilafs.h"
 
39
#endif
 
40
#include <afs/ptclient.h>
 
41
#include <afs/cmd.h>
 
42
#include <krb5.h>
 
43
 
 
44
#ifdef HAVE_KRB5_CREDS_KEYBLOCK
 
45
#define USING_MIT 1
 
46
#endif
 
47
#ifdef HAVE_KRB5_CREDS_SESSION
 
48
#define USING_HEIMDAL 1
 
49
#endif
 
50
 
 
51
#include "assert.h"
 
52
#include "skipwrap.h"
 
53
 
 
54
/* This code borrowed heavily from the previous version of log.  Here is the
 
55
   intro comment for that program: */
 
56
 
 
57
/*
 
58
        log -- tell the Andrew Cache Manager your password
 
59
        5 June 1985
 
60
        modified
 
61
        February 1986
 
62
 
 
63
        Further modified in August 1987 to understand cell IDs.
 
64
 
 
65
        Further modified in October 2006 to understand kerberos 5.
 
66
 */
 
67
 
 
68
/* Current Usage:
 
69
     klog [principal [password]] [-t] [-c cellname] [-k <k5realm>]
 
70
 
 
71
     where:
 
72
       principal is of the form 'name' or 'name@cell' which provides the
 
73
          cellname.  See the -c option below.
 
74
       password is the user's password.  This form is NOT recommended for
 
75
          interactive users.
 
76
       -t advises klog to write a Kerberos style ticket file in /tmp.
 
77
       -c identifies cellname as the cell in which authentication is to take
 
78
          place.
 
79
       -k identifies an alternate kerberos realm to use provide
 
80
          authentication services for the cell.
 
81
 */
 
82
 
 
83
#define KLOGEXIT(code) rx_Finalize(); \
 
84
                       (exit(!!code))
 
85
extern int CommandProc(struct cmd_syndesc *as, char *arock);
 
86
 
 
87
static int zero_argc;
 
88
static char **zero_argv;
 
89
 
 
90
static krb5_context k5context;
 
91
static struct afsconf_dir *tdir;
 
92
static int always_evil = 2;     /* gcc optimizes 0 into bss.  fools. */
 
93
 
 
94
int
 
95
main(int argc, char *argv[])
 
96
{
 
97
    struct cmd_syndesc *ts;
 
98
    afs_int32 code;
 
99
#ifdef  AFS_AIX32_ENV
 
100
    /*
 
101
     * The following signal action for AIX is necessary so that in case of a 
 
102
     * crash (i.e. core is generated) we can include the user's data section 
 
103
     * in the core dump. Unfortunately, by default, only a partial core is
 
104
     * generated which, in many cases, isn't too useful.
 
105
     */
 
106
    struct sigaction nsa;
 
107
 
 
108
    sigemptyset(&nsa.sa_mask);
 
109
    nsa.sa_handler = SIG_DFL;
 
110
    nsa.sa_flags = SA_FULLDUMP;
 
111
    sigaction(SIGABRT, &nsa, NULL);
 
112
    sigaction(SIGSEGV, &nsa, NULL);
 
113
#endif
 
114
    zero_argc = argc;
 
115
    zero_argv = argv;
 
116
 
 
117
    ts = cmd_CreateSyntax(NULL, CommandProc, 0,
 
118
                          "obtain Kerberos authentication");
 
119
 
 
120
#define aXFLAG 0
 
121
#define aPRINCIPAL 1
 
122
#define aPASSWORD 2
 
123
#define aCELL 3
 
124
#define aKRBREALM 4
 
125
#define aPIPE 5
 
126
#define aSILENT 6
 
127
#define aLIFETIME 7
 
128
#define aSETPAG 8
 
129
#define aTMP 9
 
130
#define aNOPRDB 10
 
131
#define aUNWRAP 11
 
132
#define aK5 12
 
133
#define aK4 13
 
134
 
 
135
    cmd_AddParm(ts, "-x", CMD_FLAG, CMD_OPTIONAL|CMD_HIDDEN, 0);
 
136
    cmd_Seek(ts, aPRINCIPAL);
 
137
    cmd_AddParm(ts, "-principal", CMD_SINGLE, CMD_OPTIONAL, "user name");
 
138
    cmd_AddParm(ts, "-password", CMD_SINGLE, CMD_OPTIONAL, "user's password");
 
139
    cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");
 
140
    cmd_AddParm(ts, "-k", CMD_SINGLE, CMD_OPTIONAL, "krb5 realm");
 
141
    cmd_AddParm(ts, "-pipe", CMD_FLAG, CMD_OPTIONAL,
 
142
                "read password from stdin");
 
143
    cmd_AddParm(ts, "-silent", CMD_FLAG, CMD_OPTIONAL, "silent operation");
 
144
    cmd_AddParm(ts, "-lifetime", CMD_SINGLE, CMD_OPTIONAL,
 
145
                "ticket lifetime in hh[:mm[:ss]]");
 
146
    cmd_AddParm(ts, "-setpag", CMD_FLAG, CMD_OPTIONAL,
 
147
                "Create a new setpag before authenticating");
 
148
    cmd_AddParm(ts, "-tmp", CMD_FLAG, CMD_OPTIONAL,
 
149
                "write Kerberos-style ticket file in /tmp");
 
150
    cmd_AddParm(ts, "-noprdb", CMD_FLAG, CMD_OPTIONAL, "don't consult pt");
 
151
    cmd_AddParm(ts, "-unwrap", CMD_FLAG, CMD_OPTIONAL, "perform 524d conversion");
 
152
#ifdef AFS_RXK5
 
153
    cmd_AddParm(ts, "-k5", CMD_FLAG, CMD_OPTIONAL, "get rxk5 credentials");
 
154
    cmd_AddParm(ts, "-k4", CMD_FLAG, CMD_OPTIONAL, "get rxkad credentials");
 
155
#else
 
156
    ++ts->nParms;       /* skip -k5 */
 
157
    cmd_AddParm(ts, "-k4", CMD_FLAG, CMD_OPTIONAL|CMD_HIDDEN, 0);
 
158
#endif
 
159
 
 
160
    code = cmd_Dispatch(argc, argv);
 
161
    KLOGEXIT(code);
 
162
}
 
163
 
 
164
static char *
 
165
getpipepass(void)
 
166
{
 
167
    static char gpbuf[BUFSIZ];
 
168
    /* read a password from stdin, stop on \n or eof */
 
169
    register int i, tc;
 
170
    memset(gpbuf, 0, sizeof(gpbuf));
 
171
    for (i = 0; i < (sizeof(gpbuf) - 1); i++) {
 
172
        tc = fgetc(stdin);
 
173
        if (tc == '\n' || tc == EOF)
 
174
            break;
 
175
        gpbuf[i] = tc;
 
176
    }
 
177
    return gpbuf;
 
178
}
 
179
 
 
180
void
 
181
silent_errors(const char *who,
 
182
    afs_int32 code,
 
183
    const char *fmt,
 
184
    va_list ap)
 
185
{
 
186
    /* ignore and don't print error */
 
187
}
 
188
 
 
189
#if defined(HAVE_KRB5_PRINC_SIZE) || defined(krb5_princ_size)
 
190
 
 
191
#define get_princ_str(c, p, n) krb5_princ_component(c, p, n)->data
 
192
#define get_princ_len(c, p, n) krb5_princ_component(c, p, n)->length
 
193
#define num_comp(c, p) (krb5_princ_size(c, p))
 
194
#define realm_data(c, p) krb5_princ_realm(c, p)->data
 
195
#define realm_len(c, p) krb5_princ_realm(c, p)->length
 
196
 
 
197
#elif defined(HAVE_KRB5_PRINCIPAL_GET_COMP_STRING)
 
198
 
 
199
#define get_princ_str(c, p, n) krb5_principal_get_comp_string(c, p, n)
 
200
#define get_princ_len(c, p, n) strlen(krb5_principal_get_comp_string(c, p, n))
 
201
#define num_comp(c, p) ((p)->name.name_string.len)
 
202
#define realm_data(c, p) krb5_realm_data(krb5_principal_get_realm(c, p))
 
203
#define realm_len(c, p) krb5_realm_length(krb5_principal_get_realm(c, p))
 
204
 
 
205
#else
 
206
#error "Must have either krb5_princ_size or krb5_principal_get_comp_string"
 
207
#endif
 
208
 
 
209
#if defined(HAVE_KRB5_CREDS_KEYBLOCK)
 
210
 
 
211
#define get_cred_keydata(c) c->keyblock.contents
 
212
#define get_cred_keylen(c) c->keyblock.length
 
213
#define get_creds_enctype(c) c->keyblock.enctype
 
214
 
 
215
#elif defined(HAVE_KRB5_CREDS_SESSION)
 
216
 
 
217
#define get_cred_keydata(c) c->session.keyvalue.data
 
218
#define get_cred_keylen(c) c->session.keyvalue.length
 
219
#define get_creds_enctype(c) c->session.keytype
 
220
 
 
221
#else
 
222
#error "Must have either keyblock or session member of krb5_creds"
 
223
#endif
 
224
 
 
225
static int
 
226
whoami(struct ktc_token *atoken,
 
227
    struct afsconf_cell *cellconfig,
 
228
    struct ktc_principal *aclient,
 
229
    int *vicep)
 
230
{
 
231
    int scIndex;
 
232
    int code;
 
233
    int i;
 
234
    struct ubik_client *ptconn = 0;
 
235
    struct rx_securityClass *sc;
 
236
    struct rx_connection *conns[MAXSERVERS+1];
 
237
    idlist lids[1];
 
238
    namelist lnames[1];
 
239
    char tempname[PR_MAXNAMELEN + 1];
 
240
 
 
241
    memset(lnames, 0, sizeof *lnames);
 
242
    memset(lids, 0, sizeof *lids);
 
243
    scIndex = 2;
 
244
    sc = rxkad_NewClientSecurityObject(rxkad_auth,
 
245
        &atoken->sessionKey, atoken->kvno,
 
246
        atoken->ticketLen, atoken->ticket);
 
247
    for (i = 0; i < cellconfig->numServers; ++i)
 
248
        conns[i] = rx_NewConnection(cellconfig->hostAddr[i].sin_addr.s_addr,
 
249
                cellconfig->hostAddr[i].sin_port, PRSRV, sc, scIndex);
 
250
    conns[i] = 0;
 
251
    ptconn = 0;
 
252
    if ((code = ubik_ClientInit(conns, &ptconn)))
 
253
        goto Failed;
 
254
    if (*aclient->instance)
 
255
        snprintf (tempname, sizeof tempname, "%s.%s",
 
256
            aclient->name, aclient->instance);
 
257
    else
 
258
        snprintf (tempname, sizeof tempname, "%s", aclient->name);
 
259
    lnames->namelist_len = 1;
 
260
    lnames->namelist_val = (prname *) tempname;
 
261
    code = ubik_PR_NameToID(ptconn, 0, lnames, lids);
 
262
    if (lids->idlist_val) {
 
263
        *vicep = *lids->idlist_val;
 
264
    }
 
265
Failed:
 
266
    if (lids->idlist_val) free(lids->idlist_val);
 
267
    if (ptconn) ubik_ClientDestroy(ptconn);
 
268
    return code;
 
269
}
 
270
 
 
271
static void
 
272
k5_to_k4_name(krb5_context k5context,
 
273
    krb5_principal k5princ,
 
274
    struct ktc_principal *ktcprinc)
 
275
{
 
276
    int i;
 
277
 
 
278
    switch(num_comp(k5context, k5princ)) {
 
279
        default:
 
280
        /* case 2: */
 
281
            i = get_princ_len(k5context, k5princ, 1);
 
282
            if (i > MAXKTCNAMELEN-1) i = MAXKTCNAMELEN-1;
 
283
            memcpy(ktcprinc->instance, get_princ_str(k5context, k5princ, 1), i);
 
284
            /* fall through */
 
285
        case 1:
 
286
            i = get_princ_len(k5context, k5princ, 0);
 
287
            if (i > MAXKTCNAMELEN-1) i = MAXKTCNAMELEN-1;
 
288
            memcpy(ktcprinc->name, get_princ_str(k5context, k5princ, 0), i);
 
289
            /* fall through */
 
290
        case 0:
 
291
            break;
 
292
        }
 
293
}
 
294
 
 
295
/* save and reuse password.  This is necessary to make
 
296
 *  "direct to service" authentication work with most
 
297
 *  flavors of kerberos, when the afs principal has no instance.
 
298
 */
 
299
struct kp_arg {
 
300
    char **pp, *pstore;
 
301
};
 
302
krb5_error_code
 
303
klog_prompter(krb5_context context,
 
304
    void *a,
 
305
    const char *name,
 
306
    const char *banner,
 
307
    int num_prompts,
 
308
    krb5_prompt prompts[])
 
309
{
 
310
    krb5_error_code code;
 
311
    int i, type;
 
312
#if !defined(USING_HEIMDAL) && defined(HAVE_KRB5_GET_PROMPT_TYPES)
 
313
    krb5_prompt_type *types;
 
314
#endif
 
315
    struct kp_arg *kparg = (struct kp_arg *) a;
 
316
    code = krb5_prompter_posix(context, a, name, banner, num_prompts, prompts);
 
317
    if (code) return code;
 
318
#if !defined(USING_HEIMDAL) && defined(HAVE_KRB5_GET_PROMPT_TYPES)
 
319
    if ((types = krb5_get_prompt_types(context)))
 
320
#endif
 
321
    for (i = 0; i < num_prompts; ++i) {
 
322
#if !defined(USING_HEIMDAL) 
 
323
#if defined(HAVE_KRB5_GET_PROMPT_TYPES)
 
324
        type = types[i];
 
325
#elif defined(HAVE_KRB5_PROMPT_TYPE)    
 
326
        type = prompts[i].type;
 
327
#else
 
328
        /* AIX 5.3 krb5_get_prompt_types is missing. Um... */
 
329
        type = ((i == 1)&&(num_prompts == 2)) ? 
 
330
          KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN : KRB5_PROMPT_TYPE_PASSWORD;
 
331
#endif
 
332
#else
 
333
        type = prompts[i].type;
 
334
#endif
 
335
#if 0
 
336
        printf ("i%d t%d <%.*s>\n", i, type, prompts[i].reply->length,
 
337
                prompts[i].reply->data);
 
338
#endif
 
339
        switch(type) {
 
340
        case KRB5_PROMPT_TYPE_PASSWORD:
 
341
        case KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN:
 
342
            memcpy(kparg->pstore, prompts[i].reply->data, prompts[i].reply->length);
 
343
            kparg->pstore[prompts[i].reply->length] = 0;
 
344
            *kparg->pp = kparg->pstore;
 
345
        }
 
346
    }
 
347
    return 0;
 
348
}
 
349
 
 
350
int
 
351
CommandProc(struct cmd_syndesc *as, char *arock)
 
352
{
 
353
    krb5_principal princ = 0;
 
354
    char *cell, *pname, **hrealms, *service;
 
355
    char service_temp[MAXKTCREALMLEN + 20];
 
356
    krb5_creds incred[1], mcred[1], *outcred = 0, *afscred;
 
357
    krb5_ccache cc = 0;
 
358
    krb5_get_init_creds_opt gic_opts[1];
 
359
    char *tofree, *outname;
 
360
    int code;
 
361
    char *what;
 
362
    int i, dosetpag, evil, noprdb, id;
 
363
#ifdef AFS_RXK5
 
364
    int authtype;
 
365
#endif
 
366
    krb5_data enc_part[1];
 
367
    time_t lifetime;            /* requested ticket lifetime */
 
368
    krb5_prompter_fct pf = NULL;
 
369
    char *pass = 0;
 
370
    void *pa = 0;
 
371
    struct kp_arg klog_arg[1];
 
372
 
 
373
    char passwd[BUFSIZ];
 
374
    struct afsconf_cell cellconfig[1];
 
375
 
 
376
    static char rn[] = "klog";  /*Routine name */
 
377
    static int Pipe = 0;        /* reading from a pipe */
 
378
    static int Silent = 0;      /* Don't want error messages */
 
379
 
 
380
    int writeTicketFile = 0;    /* write ticket file to /tmp */
 
381
 
 
382
    service = 0;
 
383
    memset(incred, 0, sizeof *incred);
 
384
    /* blow away command line arguments */
 
385
    for (i = 1; i < zero_argc; i++)
 
386
        memset(zero_argv[i], 0, strlen(zero_argv[i]));
 
387
    zero_argc = 0;
 
388
    memset(klog_arg, 0, sizeof *klog_arg);
 
389
 
 
390
    /* first determine quiet flag based on -silent switch */
 
391
    Silent = (as->parms[aSILENT].items ? 1 : 0);
 
392
 
 
393
    if (Silent) {
 
394
        afs_set_com_err_hook(silent_errors);
 
395
    }
 
396
 
 
397
    if ((code = krb5_init_context(&k5context))) {
 
398
        afs_com_err(rn, code, "while initializing Kerberos 5 library");
 
399
        KLOGEXIT(code);
 
400
    }
 
401
    if ((code = rx_Init(0))) {
 
402
        afs_com_err(rn, code, "while initializing rx");
 
403
        KLOGEXIT(code);
 
404
    }
 
405
    initialize_U_error_table();
 
406
    /*initialize_krb5_error_table();*/ 
 
407
    initialize_RXK_error_table();
 
408
    initialize_KTC_error_table();
 
409
    initialize_ACFG_error_table();
 
410
    /* initialize_rx_error_table(); */
 
411
    if (!(tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH))) {
 
412
        afs_com_err(rn, 0, "can't get afs configuration (afsconf_Open(%s))",
 
413
            rn, AFSDIR_CLIENT_ETC_DIRPATH);
 
414
        KLOGEXIT(1);
 
415
    }
 
416
 
 
417
    /* Parse remaining arguments. */
 
418
 
 
419
    dosetpag = !! as->parms[aSETPAG].items;
 
420
    Pipe = !! as->parms[aPIPE].items;
 
421
    writeTicketFile = !! as->parms[aTMP].items;
 
422
    noprdb = !! as->parms[aNOPRDB].items;
 
423
    evil = (always_evil&1) || !! as->parms[aUNWRAP].items;
 
424
 
 
425
#ifdef AFS_RXK5
 
426
    authtype = 0;
 
427
    if (as->parms[aK5].items)
 
428
        authtype |= FORCE_RXK5;
 
429
    if (as->parms[aK4].items)
 
430
        authtype |= FORCE_RXKAD;
 
431
    if (!authtype)
 
432
        authtype |= env_afs_rxk5_default();
 
433
#endif
 
434
 
 
435
    cell = as->parms[aCELL].items ? as->parms[aCELL].items->data : 0;
 
436
    if ((code = afsconf_GetCellInfo(tdir, cell, "afsprot", cellconfig))) {
 
437
        if (cell)
 
438
            afs_com_err(rn, code, "Can't get cell information for '%s'", cell);
 
439
        else
 
440
            afs_com_err(rn, code, "Can't get determine local cell!");
 
441
        KLOGEXIT(code);
 
442
    }
 
443
 
 
444
    if (as->parms[aKRBREALM].items) {
 
445
        code = krb5_set_default_realm(k5context,
 
446
                (const char *) as->parms[aKRBREALM].items);
 
447
        if (code) {
 
448
            afs_com_err(rn, code, "Can't make <%s> the default realm",
 
449
                as->parms[aKRBREALM].items);
 
450
            KLOGEXIT(code);
 
451
        }
 
452
    }
 
453
    else if ((code = krb5_get_host_realm(k5context, cellconfig->hostName[0], &hrealms))) {
 
454
        afs_com_err(rn, code, "Can't get realm for host <%s> in cell <%s>\n",
 
455
                cellconfig->hostName[0], cellconfig->name);
 
456
        KLOGEXIT(code);
 
457
    } else {
 
458
        if (hrealms && *hrealms) {
 
459
            code = krb5_set_default_realm(k5context,
 
460
                    *hrealms);
 
461
            if (code) {
 
462
                afs_com_err(rn, code, "Can't make <%s> the default realm",
 
463
                    *hrealms);
 
464
                KLOGEXIT(code);
 
465
            }
 
466
        }
 
467
        if (hrealms) krb5_free_host_realm(k5context, hrealms);
 
468
    }
 
469
 
 
470
    id = getuid();
 
471
    if (as->parms[aPRINCIPAL].items) {
 
472
        pname = as->parms[aPRINCIPAL].items->data;
 
473
    } else {
 
474
        /* No explicit name provided: use Unix uid. */
 
475
        struct passwd *pw;
 
476
        pw = getpwuid(id);
 
477
        if (pw == 0) {
 
478
            afs_com_err(rn, 0,
 
479
                "Can't figure out your name from your user id (%d).", id);
 
480
            if (!Silent)
 
481
                fprintf(stderr, "%s: Try providing the user name.\n", rn);
 
482
            KLOGEXIT(1);
 
483
        }
 
484
        pname = pw->pw_name;
 
485
    }
 
486
    code = krb5_parse_name(k5context, pname, &princ);
 
487
    if (code) {
 
488
        afs_com_err(rn, code, "Can't parse principal <%s>", pname);
 
489
        KLOGEXIT(code);
 
490
    }
 
491
 
 
492
    if (as->parms[aPASSWORD].items) {
 
493
        /*
 
494
         * Current argument is the desired password string.  Remember it in
 
495
         * our local buffer, and zero out the argument string - anyone can
 
496
         * see it there with ps!
 
497
         */
 
498
        strncpy(passwd, as->parms[aPASSWORD].items->data, sizeof(passwd));
 
499
        memset(as->parms[aPASSWORD].items->data, 0,
 
500
               strlen(as->parms[aPASSWORD].items->data));
 
501
        pass = passwd;
 
502
    }
 
503
 
 
504
    if (as->parms[aLIFETIME].items) {
 
505
        char *life = as->parms[aLIFETIME].items->data;
 
506
        char *sp;               /* string ptr to rest of life */
 
507
        lifetime = 3600 * strtol(life, &sp, 0); /* hours */
 
508
        if (sp == life) {
 
509
          bad_lifetime:
 
510
            if (!Silent)
 
511
                fprintf(stderr, "%s: translating '%s' to lifetime failed\n",
 
512
                        rn, life);
 
513
            return 1;
 
514
        }
 
515
        if (*sp == ':') {
 
516
            life = sp + 1;      /* skip the colon */
 
517
            lifetime += 60 * strtol(life, &sp, 0);      /* minutes */
 
518
            if (sp == life)
 
519
                goto bad_lifetime;
 
520
            if (*sp == ':') {
 
521
                life = sp + 1;
 
522
                lifetime += strtol(life, &sp, 0);       /* seconds */
 
523
                if (sp == life)
 
524
                    goto bad_lifetime;
 
525
                if (*sp)
 
526
                    goto bad_lifetime;
 
527
            } else if (*sp)
 
528
                goto bad_lifetime;
 
529
        } else if (*sp)
 
530
            goto bad_lifetime;
 
531
    } else
 
532
        lifetime = 0;
 
533
 
 
534
    /* Get the password if it wasn't provided. */
 
535
    if (!pass) {
 
536
        if (Pipe) {
 
537
            strncpy(passwd, getpipepass(), sizeof(passwd));
 
538
            pass = passwd;
 
539
        } else {
 
540
            pf = klog_prompter;
 
541
            pa = (char *)klog_arg;
 
542
        }
 
543
    }
 
544
 
 
545
    service = 0;
 
546
#ifdef AFS_RXK5
 
547
    if (authtype & FORCE_RXK5) {
 
548
        tofree = get_afs_krb5_svc_princ(cellconfig);
 
549
        snprintf(service_temp, sizeof service_temp, "%s", tofree);
 
550
    } else
 
551
#endif
 
552
    snprintf (service_temp, sizeof service_temp, "afs/%s", cellconfig->name);
 
553
    if (writeTicketFile)
 
554
        service = 0;
 
555
    else 
 
556
        service = service_temp;
 
557
 
 
558
    klog_arg->pp = &pass;
 
559
    klog_arg->pstore = passwd;
 
560
    /* XXX should allow k5 to prompt in most cases -- what about expired pw?*/
 
561
    krb5_get_init_creds_opt_init(gic_opts);
 
562
    for (;;) {
 
563
        code = krb5_get_init_creds_password(k5context,
 
564
            incred,
 
565
            princ,
 
566
            pass,
 
567
            pf, /* prompter */
 
568
            pa, /* data */
 
569
            0,  /* start_time */
 
570
            service,    /* in_tkt_service */
 
571
            gic_opts);
 
572
        if (code != KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || service != service_temp) break;
 
573
#ifdef AFS_RXK5
 
574
        if (authtype & FORCE_RXK5) break;
 
575
#endif
 
576
        service = "afs";
 
577
    }
 
578
    memset(passwd, 0, sizeof(passwd));
 
579
    if (code) {
 
580
        char *r = 0;
 
581
        if (krb5_get_default_realm(k5context, &r))
 
582
            r = 0;
 
583
        if (service)
 
584
            afs_com_err(rn, code, "Unable to authenticate to use %s", service);
 
585
        else if (r)
 
586
            afs_com_err(rn, code, "Unable to authenticate in realm %s", r);
 
587
        else
 
588
            afs_com_err(rn, code, "Unable to authenticate to use cell %s",
 
589
                cellconfig->name);
 
590
        if (r) free(r);
 
591
        KLOGEXIT(code);
 
592
    }
 
593
 
 
594
    if (service) {
 
595
        afscred = incred;
 
596
    } else {
 
597
        for (;;writeTicketFile = 0) {
 
598
            if (writeTicketFile) {
 
599
                what = "getting default ccache";
 
600
                code = krb5_cc_default(k5context, &cc);
 
601
            } else {
 
602
                what = "krb5_cc_resolve";
 
603
                code = krb5_cc_resolve(k5context, "MEMORY:core", &cc);
 
604
                if (code) goto Failed;
 
605
            }
 
606
            what = "initializing ccache";
 
607
            code = krb5_cc_initialize(k5context, cc, princ);
 
608
            if (code) goto Failed;
 
609
            what = "writing Kerberos ticket file";
 
610
            code = krb5_cc_store_cred(k5context, cc, incred);
 
611
            if (code) goto Failed;
 
612
            if (writeTicketFile)
 
613
                fprintf(stderr,
 
614
                    "Wrote ticket file to %s\n",
 
615
                    krb5_cc_get_name(k5context, cc));
 
616
            break;
 
617
        Failed:
 
618
            if (code)
 
619
                afs_com_err(rn, code, what);
 
620
            if (writeTicketFile) {
 
621
                if (cc) {
 
622
                    krb5_cc_close(k5context, cc);
 
623
                    cc = 0;
 
624
                }
 
625
                continue;
 
626
            }
 
627
            KLOGEXIT(code);
 
628
        }
 
629
 
 
630
        for (service = service_temp;;service = "afs") {
 
631
            memset(mcred, 0, sizeof *mcred);
 
632
            mcred->client = princ;
 
633
            code = krb5_parse_name(k5context, service, &mcred->server);
 
634
            if (code) {
 
635
                afs_com_err(rn, code, "Unable to parse service <%s>\n", service);
 
636
                KLOGEXIT(code);
 
637
            }
 
638
            if (tofree) { free(tofree); tofree = 0; }
 
639
            if (!(code = krb5_unparse_name(k5context, mcred->server, &outname)))
 
640
                tofree = outname;
 
641
            else outname = service;
 
642
            code = krb5_get_credentials(k5context, 0, cc, mcred, &outcred);
 
643
            krb5_free_principal(k5context, mcred->server);
 
644
            if (code != KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || service != service_temp) break;
 
645
#ifdef AFS_RXK5
 
646
            if (authtype & FORCE_RXK5) break;
 
647
#endif
 
648
        }
 
649
        afscred = outcred;
 
650
    }
 
651
    if (code) {
 
652
        afs_com_err(rn, code, "Unable to get credentials to use %s", outname);
 
653
        KLOGEXIT(code);
 
654
    }
 
655
 
 
656
#ifdef AFS_RXK5
 
657
    if (authtype & FORCE_RXK5) {
 
658
        struct ktc_principal aserver[1];
 
659
        int viceid = 555;
 
660
 
 
661
        memset(aserver, 0, sizeof *aserver);
 
662
        strncpy(aserver->cell, cellconfig->name, MAXKTCREALMLEN-1);
 
663
        code = ktc_SetK5Token(k5context, aserver, afscred, viceid, dosetpag);
 
664
        if (code) {
 
665
            afs_com_err(rn, code, "Unable to store tokens for cell %s\n",
 
666
                cellconfig->name);
 
667
            KLOGEXIT(1);
 
668
        }
 
669
    } else
 
670
#endif
 
671
    {
 
672
        struct ktc_principal aserver[1], aclient[1];
 
673
        struct ktc_token atoken[1];
 
674
 
 
675
        memset(atoken, 0, sizeof *atoken);
 
676
        if (evil) {
 
677
            atoken->kvno = RXKAD_TKT_TYPE_KERBEROS_V5_ENCPART_ONLY;
 
678
            if (afs_krb5_skip_ticket_wrapper(afscred->ticket.data,
 
679
                        afscred->ticket.length, &enc_part->data,
 
680
                        &enc_part->length)) {
 
681
                afs_com_err(rn, 0, "Can't unwrap %s AFS credential",
 
682
                    cellconfig->name);
 
683
                KLOGEXIT(1);
 
684
            }
 
685
        } else {
 
686
            atoken->kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
 
687
            *enc_part = afscred->ticket;
 
688
        }
 
689
        atoken->startTime = afscred->times.starttime;
 
690
        atoken->endTime = afscred->times.endtime;
 
691
        memcpy(&atoken->sessionKey, get_cred_keydata(afscred),
 
692
            get_cred_keylen(afscred));
 
693
        memcpy(atoken->ticket, enc_part->data,
 
694
            atoken->ticketLen = enc_part->length);
 
695
        memset(aserver, 0, sizeof *aserver);
 
696
        strncpy(aserver->name, "afs", 4);
 
697
        strncpy(aserver->cell, cellconfig->name, MAXKTCREALMLEN-1);
 
698
        memset(aclient, 0, sizeof *aclient);
 
699
        i = realm_len(k5context, afscred->client);
 
700
        if (i > MAXKTCREALMLEN-1) i = MAXKTCREALMLEN-1;
 
701
        memcpy(aclient->cell, realm_data(k5context, afscred->client), i);
 
702
        if (!noprdb) {
 
703
            int viceid;
 
704
            k5_to_k4_name(k5context, afscred->client, aclient);
 
705
            code = whoami(atoken, cellconfig, aclient, &viceid);
 
706
            if (code) {
 
707
                afs_com_err(rn, code, "Can't get your viceid", cellconfig->name);
 
708
                *aclient->name = 0;
 
709
            } else
 
710
                snprintf(aclient->name, MAXKTCNAMELEN-1, "AFS ID %d", viceid);
 
711
        }
 
712
        if (!*aclient->name)
 
713
            k5_to_k4_name(k5context, afscred->client, aclient);
 
714
        code = ktc_SetToken(aserver, atoken, aclient, dosetpag);
 
715
        if (code) {
 
716
            afs_com_err(rn, code, "Unable to store tokens for cell %s\n",
 
717
                cellconfig->name);
 
718
            KLOGEXIT(1);
 
719
        }
 
720
    }
 
721
 
 
722
    krb5_free_principal(k5context, princ);
 
723
    krb5_free_cred_contents(k5context, incred);
 
724
    if (outcred) krb5_free_creds(k5context, outcred);
 
725
    if (cc)
 
726
        krb5_cc_close(k5context, cc);
 
727
    if (tofree) free(tofree);
 
728
 
 
729
    return 0;
 
730
}