source: trunk/athena/lib/locker/afs.c @ 22680

Revision 22680, 20.6 KB checked in by rbasch, 17 years ago (diff)
Fix bugs [27154]; diagnosed by geofft. * athena/lib/locker/afs.c (afs_maybe_auth_to_cell): Don't free() the memory for the user variable prematurely.
Line 
1/* Copyright 1998 by the Massachusetts Institute of Technology.
2 *
3 * Permission to use, copy, modify, and distribute this
4 * software and its documentation for any purpose and without
5 * fee is hereby granted, provided that the above copyright
6 * notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting
8 * documentation, and that the name of M.I.T. not be used in
9 * advertising or publicity pertaining to distribution of the
10 * software without specific, written prior permission.
11 * M.I.T. makes no representations about the suitability of
12 * this software for any purpose.  It is provided "as is"
13 * without express or implied warranty.
14 */
15
16/* This file is part of liblocker. It implements AFS lockers. */
17
18static const char rcsid[] = "$Id: afs.c,v 1.16 2006-08-08 21:50:09 ghudson Exp $";
19
20#include <sys/types.h>
21#include <sys/socket.h>
22#include <sys/stat.h>
23#include <errno.h>
24#include <netdb.h>
25#include <stdlib.h>
26#include <string.h>
27#include <unistd.h>
28
29#include <afs/stds.h>
30#include <afs/param.h>
31#include <afs/auth.h>
32#include <afs/cellconfig.h>
33#include <afs/ptserver.h>
34#include <afs/ptuser.h>
35#include <afs/venus.h>
36#include <rx/rxkad.h>
37
38/* This is defined in <afs/volume.h>, but it doesn't seem possible to
39 * include that without dragging in most of the rest of the afs
40 * includes as dependencies.
41 */
42#define VNAMESIZE 32
43
44#include <com_err.h>
45#include <krb.h>
46#include <krb5.h>
47
48#include "locker.h"
49#include "locker_private.h"
50
51/* Cheesy test for determining AFS 3.5. */
52#ifndef AFSCONF_CLIENTNAME
53#define AFS35
54#endif
55
56#ifdef AFS35
57#include <afs/dirpath.h>
58#else
59#define AFSDIR_CLIENT_ETC_DIRPATH AFSCONF_CLIENTNAME
60#endif
61
62/*
63 * Why doesn't AFS provide this prototype?
64 */
65extern int pioctl(char *, afs_int32, struct ViceIoctl *, afs_int32);
66
67static int afs_parse(locker_context context, char *name, char *desc,
68                     char *mountpoint, locker_attachent **at);
69static int afs_attach(locker_context context, locker_attachent *at,
70                      char *mountoptions);
71static int afs_detach(locker_context context, locker_attachent *at);
72static int afs_auth(locker_context context, locker_attachent *at,
73                    int mode, int op);
74static int afs_zsubs(locker_context context, locker_attachent *at);
75
76struct locker_ops locker__afs_ops = {
77  "AFS",
78  0,
79  afs_parse,
80  afs_attach,
81  afs_detach,
82  afs_auth,
83  afs_zsubs
84};
85
86static int afs_get_cred(krb5_context context, char *name, char *inst, char *realm,
87                        krb5_creds **creds);
88static int afs_maybe_auth_to_cell(locker_context context, char *name,
89                                  char *cell, int op, int force);
90static int get_user_realm(krb5_context context, char *realm);
91static char *afs_realm_of_cell(krb5_context, struct afsconf_cell *);
92
93extern int krb524_convert_creds_kdc(krb5_context, krb5_creds *, CREDENTIALS *);
94
95static int afs_parse(locker_context context, char *name, char *desc,
96                     char *mountpoint, locker_attachent **atp)
97{
98  locker_attachent *at;
99  char *p, *dup = NULL, *lasts = NULL;
100  int status;
101
102  at = locker__new_attachent(context, &locker__afs_ops);
103  if (!at)
104    return LOCKER_ENOMEM;
105
106  if (!name)
107    {
108      /* This is an explicit description. */
109
110      if (strncmp(desc, "/afs/", 5))
111        {
112          locker__error(context, "%s: Path is not in AFS.\n", desc);
113          status = LOCKER_EPARSE;
114          goto cleanup;
115        }
116
117      at->name = strdup(desc);
118      at->hostdir = strdup(desc);
119      if (mountpoint)
120        at->mountpoint = strdup(mountpoint);
121      else
122        {
123          p = strrchr(desc, '/') + 1;
124          at->mountpoint = malloc(strlen(context->afs_mount_dir) +
125                                  strlen(p) + 2);
126          if (at->mountpoint)
127            sprintf(at->mountpoint, "%s/%s", context->afs_mount_dir, p);
128        }
129      if (!at->name || !at->hostdir || !at->mountpoint)
130        goto mem_error;
131
132      at->mode = LOCKER_AUTH_READWRITE;
133    }
134  else
135    {
136      /* A Hesiod AFS description looks like:
137       * AFS /afs/dev.mit.edu/source/src-current w /mit/source
138       */
139
140      at->name = strdup(name);
141      if (!at->name)
142        goto mem_error;
143
144      dup = strdup(desc);
145      if (!dup)
146        goto mem_error;
147
148      /* Skip "AFS". */
149      if (!strtok_r(dup, " ", &lasts))
150        goto parse_error;
151
152      /* Hostdir */
153      at->hostdir = strtok_r(NULL, " ", &lasts);
154      if (!at->hostdir)
155        goto parse_error;
156      if (strncmp(at->hostdir, "/afs/", 5))
157        {
158          locker__error(context, "%s: Path \"%s\" is not in AFS.\n", name,
159                        at->hostdir);
160          status = LOCKER_EPARSE;
161          goto cleanup;
162        }
163      at->hostdir = strdup(at->hostdir);
164      if (!at->hostdir)
165        goto mem_error;
166
167      /* Auth mode */
168      p = strtok_r(NULL, " ", &lasts);
169      if (!p || *(p + 1))
170        goto parse_error;
171
172      switch (*p)
173        {
174        case 'r':
175          at->mode = LOCKER_AUTH_READONLY;
176          break;
177        case 'w':
178          at->mode = LOCKER_AUTH_READWRITE;
179          break;
180        case 'n':
181          at->mode = LOCKER_AUTH_NONE;
182          break;
183        default:
184          locker__error(context, "%s: Unrecognized auth mode '%c' in "
185                        "description:\n%s\n", name, *p, desc);
186          status = LOCKER_EPARSE;
187          goto cleanup;
188        }
189
190      /* Mountpoint */
191      p = strtok_r(NULL, " ", &lasts);
192      if (!p)
193        goto parse_error;
194      if (mountpoint)
195        at->mountpoint = strdup(mountpoint);
196      else
197        at->mountpoint = strdup(p);
198      if (!at->mountpoint)
199        goto mem_error;
200
201      free(dup);
202      dup = NULL;
203    }
204
205  status = locker__canonicalize_path(context, LOCKER_CANON_CHECK_MOST,
206                                     &(at->mountpoint), &(at->buildfrom));
207  if (status != LOCKER_SUCCESS)
208    goto cleanup;
209
210  *atp = at;
211  return LOCKER_SUCCESS;
212
213mem_error:
214  locker__error(context, "Out of memory parsing locker description.\n");
215  status = LOCKER_ENOMEM;
216  goto cleanup;
217
218parse_error:
219  locker__error(context, "Could not parse locker description "
220                "\"%s\".\n", desc);
221  status = LOCKER_EPARSE;
222
223cleanup:
224  free(dup);
225  locker_free_attachent(context, at);
226  return status;
227}
228
229static int afs_attach(locker_context context, locker_attachent *at,
230                      char *mountoptions)
231{
232  struct stat st1, st2;
233  struct ViceIoctl vio;
234  afs_int32 hosts[8]; /* AFS docs say VIOCWHEREIS won't return more than 8. */
235  uid_t uid = geteuid();
236  int status;
237
238  /* Make sure user can read the destination, and it's a directory. */
239  if (uid != context->user)
240    seteuid(context->user);
241  status = lstat(at->hostdir, &st1);
242  if (uid != context->user)
243    seteuid(uid);
244
245  if (status == -1)
246    {
247     if (errno == ETIMEDOUT)
248        {
249          locker__error(context, "%s: Connection timed out while trying to "
250                        "attach locker.\nThis probably indicates a temporary "
251                        "problem with the file server containing\n"
252                        "this locker. Try again later.\n", at->name);
253        }
254      else
255        {
256          locker__error(context, "%s: Could not attach locker:\n%s for %s\n",
257                        at->name, strerror(errno), at->hostdir);
258        }
259      return LOCKER_EATTACH;
260    }
261  if (!S_ISDIR(st1.st_mode) && !S_ISLNK(st1.st_mode))
262    {
263      locker__error(context, "%s: Could not attach locker:\n"
264                    "%s is not a directory.\n", at->name, at->hostdir);
265      return LOCKER_EATTACH;
266    }
267
268  /* Make sure nothing is already mounted on our mountpoint. */
269  status = stat(at->mountpoint, &st2);
270  if (!status && st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino)
271    {
272      locker__error(context, "%s: Locker is already attached.\n",
273                    at->name);
274      return LOCKER_EALREADY;
275    }
276  else if (!status || errno != ENOENT)
277    {
278      locker__error(context, "%s: Could not attach locker:\n"
279                    "Mountpoint %s is busy.\n", at->name, at->mountpoint);
280      return LOCKER_EMOUNTPOINTBUSY;
281    }
282
283  status = symlink(at->hostdir, at->mountpoint);
284  if (status < 0)
285    {
286      locker__error(context, "%s: Could not attach locker:\n%s while "
287                    "symlinking %s to %s\n", at->name, strerror(errno),
288                    at->hostdir, at->mountpoint);
289      return LOCKER_EATTACH;
290    }
291
292  /* Find host that the locker is on, and update the attachent. */
293  memset(hosts, 0, sizeof(hosts));
294  vio.in_size = 0;
295  vio.out = (caddr_t)hosts;
296  vio.out_size = sizeof(hosts);
297  if (pioctl(at->hostdir, VIOCWHEREIS, &vio, 1) == 0)
298    {
299      /* Only record the hostaddr if the locker is on a single host.
300       * (We assume that if it's on multiple hosts, it can't fail,
301       * so we don't need to know what those hosts are.)
302       */
303      if (!hosts[1])
304        at->hostaddr.s_addr = hosts[0];
305    }
306
307  return LOCKER_SUCCESS;
308}
309
310static int afs_detach(locker_context context, locker_attachent *at)
311{
312  int status;
313
314  status = unlink(at->mountpoint);
315  if (status < 0)
316    {
317      if (errno == ENOENT)
318        {
319          locker__error(context, "%s: Locker is not attached.\n", at->name);
320          return LOCKER_ENOTATTACHED;
321        }
322      else
323        {
324          locker__error(context, "%s: Could not detach locker:\n%s while "
325                        "trying to unlink %s.\n", at->name, strerror(errno),
326                        at->mountpoint);
327          return LOCKER_EDETACH;
328        }
329    }
330  return LOCKER_SUCCESS;
331}
332
333static int afs_auth(locker_context context, locker_attachent *at,
334                    int mode, int op)
335{
336  char *cell, *p;
337  int status;
338
339  if (op != LOCKER_AUTH_AUTHENTICATE)
340    return LOCKER_SUCCESS;
341
342  /* We know (from afs_parse) that at->hostdir starts with "/afs/". */
343  cell = at->hostdir + 5;
344  /* Skip initial "." in the cell name (if this is a path to a rw volume). */
345  if (*cell == '.')
346    cell++;
347
348  p = strchr(cell, '/');
349  if (p)
350    *p = '\0';
351  status = afs_maybe_auth_to_cell(context, at->name, cell, op, 0);
352  if (p)
353    *p = '/';
354  return status;
355}
356
357int locker_auth_to_cell(locker_context context, char *name, char *cell, int op)
358{
359  return afs_maybe_auth_to_cell(context, name, cell, op, 1);
360}
361
362static int afs_maybe_auth_to_cell(locker_context context, char *name,
363                                  char *cell, int op, int force)
364{
365  char *crealm, urealm[REALM_SZ], *user = NULL;
366  int status;
367  struct afsconf_dir *configdir;
368  struct afsconf_cell cellconfig;
369  struct ktc_principal server, client, xclient;
370  struct ktc_token token, xtoken;
371  afs_int32 vice_id;
372  uid_t uid = geteuid(), ruid = getuid();
373  krb5_context v5context;
374  krb5_creds *v5cred = NULL;
375
376  if (op != LOCKER_AUTH_AUTHENTICATE)
377    return LOCKER_SUCCESS;
378
379  /* Find the cell's db servers. */
380  configdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
381  if (!configdir)
382    {
383      locker__error(context, "%s: Could not authenticate to AFS: "
384                    "error opening CellServDB file.\n", name);
385      return LOCKER_EAUTH;
386    }
387  status = afsconf_GetCellInfo(configdir, cell, NULL, &cellconfig);
388  afsconf_Close(configdir);
389  if (status)
390    {
391      initialize_acfg_error_table();
392      locker__error(context, "%s: Could not authenticate to AFS:\n%s while "
393                    "reading CellServDB file.\n", name, error_message(status));
394      return LOCKER_EAUTH;
395    }
396
397  /* Canonicalize the cell name. */
398  cell = cellconfig.name;
399
400  /* Get tickets for the realm containing the cell's servers. (Set uid
401   * to the user before touching the ticket file.) Try
402   * afs.cellname@realm first, and afs@realm if that doesn't exist.
403   */
404  status = krb5_init_context(&v5context);
405  if (status)
406    {
407      locker__error(context, "%s: Could not establish krb5 context: %s\n",
408                    name, error_message(status));
409      return LOCKER_EAUTH;
410    }
411  crealm = afs_realm_of_cell(v5context, &cellconfig);
412  if (uid != ruid)
413    seteuid(ruid);
414  status = afs_get_cred(v5context, "afs", cell, crealm, &v5cred);
415  if (status)
416    status = afs_get_cred(v5context, "afs", "", crealm, &v5cred);
417  if (uid != ruid)
418    seteuid(uid);
419  if (status)
420    {
421      if (status == KRB5_FCC_NOFILE)
422        {
423          locker__error(context, "%s: Could not authenticate to AFS: %s.\n",
424                        name, error_message(status));
425        }
426      else
427        {
428          locker__error(context, "%s: Could not authenticate to AFS cell "
429                        "%s:\n%s while getting tickets for %s.\n",
430                        name, cell, error_message(status), crealm);
431        }
432      krb5_free_context(v5context);
433      return LOCKER_EAUTH;
434    }
435  status = get_user_realm(v5context, urealm);
436  if (status)
437    {
438      locker__error(context, "Couldn't obtain user's realm.\n");
439      return LOCKER_EAUTH;
440    }
441
442  /*
443   * Create a token from the ticket.
444   * (This code is shamelessly stolen from aklog.)
445   */
446
447  if (! context->use_krb4)
448    {
449      char *p;
450      char *pname, *pinst = NULL;
451      int pnamelen, pinstlen = 0;
452
453      /* Using Kerberos V5 ticket natively via rxkad 2b */
454
455      pname    = krb5_princ_component(v5context, v5cred->client, 0)->data;
456      pnamelen = krb5_princ_component(v5context, v5cred->client, 0)->length;
457
458      if (krb5_princ_size(v5context, v5cred->client) > 1)
459        {
460          pinst    = krb5_princ_component(v5context, v5cred->client, 1)->data;
461          pinstlen = krb5_princ_component(v5context, v5cred->client, 1)->length;
462        }
463
464      user = malloc(pnamelen + pinstlen + strlen(urealm) + 3);
465      if (!user)
466        {
467          locker__error(context, "Out of memory authenticating to cell.\n");
468          return LOCKER_ENOMEM;
469        }
470
471      strncpy(user, pname, pnamelen);
472      user[pnamelen] = '\0';
473
474      if (pinst)
475        {
476          strcat(user, ".");
477          p = user + strlen(user);
478          strncpy(p, pinst, pinstlen);
479          p[pinstlen] = '\0';
480        }
481
482      if (strcasecmp(crealm, urealm))
483        sprintf(user + strlen(user), "@%s", urealm);
484
485      memset(&token, 0, sizeof(token));
486      token.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
487      token.startTime = v5cred->times.starttime;;
488      token.endTime = v5cred->times.endtime;
489      memcpy(&token.sessionKey, v5cred->keyblock.contents,
490             v5cred->keyblock.length);
491      token.ticketLen = v5cred->ticket.length;
492      memcpy(token.ticket, v5cred->ticket.data, token.ticketLen);
493    }
494  else
495    {
496      CREDENTIALS cred;
497
498      /* Using Kerberos 524 translator service */
499
500      status = krb5_524_convert_creds(v5context, v5cred, &cred);
501
502      if (status)
503        {
504          locker__error(context, "%s: Could not convert tickets "
505                        "to Kerberos V4 format: %s.\n",
506                        name, error_message(status));
507          krb5_free_context(v5context);
508          return LOCKER_EAUTH;
509        }
510
511      user = malloc(strlen(cred.pname) + strlen(cred.pinst) + strlen(urealm) + 3);
512      if (!user)
513        {
514          locker__error(context, "Out of memory authenticating to cell.\n");
515          return LOCKER_ENOMEM;
516        }
517
518      strcpy(user, cred.pname);
519      if (*cred.pinst)
520        sprintf(user + strlen(user), ".%s", cred.pinst);
521      if (strcasecmp(crealm, urealm))
522        sprintf(user + strlen(user), "@%s", urealm);
523
524      token.kvno = cred.kvno;
525      token.startTime = cred.issue_date;
526      token.endTime = v5cred->times.endtime;
527      memcpy(&token.sessionKey, cred.session, sizeof(token.sessionKey));
528      token.ticketLen = cred.ticket_st.length;
529      memcpy(token.ticket, cred.ticket_st.dat, token.ticketLen);
530    }
531
532  krb5_free_creds(v5context, v5cred);
533  krb5_free_context(v5context);
534
535  /* Look up principal's PTS id. */
536  status = pr_Initialize(0, (char *)AFSDIR_CLIENT_ETC_DIRPATH, cell);
537  if (status)
538    {
539      locker__error(context, "%s: Could not initialize AFS protection "
540                    "library while authenticating to cell \"%s\":\n%s.\n",
541                    name, cell, error_message(status));
542      free(user);
543      return LOCKER_EAUTH;
544    }
545  status = pr_SNameToId(user, &vice_id);
546  if (status)
547    {
548      locker__error(context, "%s: Could not find AFS PTS id for user \"%s\""
549                    "in cell \"%s\":\n%s.\n", name, user, cell,
550                    error_message(status));
551      free(user);
552      return LOCKER_EAUTH;
553    }
554
555  /* Select appropriate dead chicken to wave. */
556  if (vice_id == ANONYMOUSID)
557    strncpy(client.name, user, MAXKTCNAMELEN - 1);
558  else
559    sprintf(client.name, "AFS ID %ld", (long) vice_id);
560  strcpy(client.instance, "");
561  strncpy(client.cell, crealm, MAXKTCREALMLEN - 1);
562  client.cell[MAXKTCREALMLEN - 1] = '\0';
563
564  strcpy(server.name, "afs");
565  strcpy(server.instance, "");
566  strncpy(server.cell, cell, MAXKTCREALMLEN - 1);
567  server.cell[MAXKTCREALMLEN - 1] = '\0';
568
569  if (!force)
570    {
571      /* Check for an existing token. */
572      status = ktc_GetToken(&server, &xtoken, sizeof(token), &xclient);
573      if (!status)
574        {
575          /* Don't get tokens as another user. */
576          if (strcmp(xclient.name, client.name))
577            {
578              free(user);
579              return LOCKER_SUCCESS;
580            }
581
582          /* Don't get tokens that won't last longer than existing tokens. */
583          if (token.endTime <= xtoken.endTime)
584            {
585              free(user);
586              return LOCKER_SUCCESS;
587            }
588        }
589    }
590
591  /* Store the token. */
592  status = ktc_SetToken(&server, &token, &client, 0);
593  if (status)
594    {
595      locker__error(context, "%s: Could not obtain %s tokens for cell "
596                    "%s:\n%s.\n", name, user, cell, error_message(status));
597      free(user);
598      return LOCKER_EAUTH;
599    }
600
601  free(user);
602  return LOCKER_SUCCESS;
603}
604
605static int afs_get_cred(krb5_context context, char *name, char *inst, char *realm,
606                        krb5_creds **creds)
607{
608  krb5_creds increds;
609  krb5_principal client_principal = NULL;
610  krb5_ccache krb425_ccache = NULL;
611  krb5_error_code retval = 0;
612
613  memset(&increds, 0, sizeof(increds));
614  /* ANL - instance may be ptr to a null string. Pass null then */
615  retval = krb5_build_principal(context, &increds.server, strlen(realm),
616                                realm, name,
617                                (inst && strlen(inst)) ? inst : NULL,
618                                NULL);
619  if (retval)
620    goto fail;
621
622  retval = krb5_cc_default(context, &krb425_ccache);
623  if (retval)
624    goto fail;
625
626  retval = krb5_cc_get_principal(context, krb425_ccache, &client_principal);
627  if (retval)
628    goto fail;
629
630  increds.client = client_principal;
631  increds.times.endtime = 0;
632  /* Ask for DES since that is what V4 understands */
633  increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
634
635  retval = krb5_get_credentials(context, 0, krb425_ccache, &increds, creds);
636
637fail:
638  krb5_free_cred_contents(context, &increds);
639  if (krb425_ccache)
640    krb5_cc_close(context, krb425_ccache);
641  return(retval);
642}
643
644static int afs_zsubs(locker_context context, locker_attachent *at)
645{
646  struct ViceIoctl vio;
647  char *path, *last_component, *p, *subs[3];
648  char cell[MAXCELLCHARS + 1], vol[VNAMESIZE + 1];
649  char cellvol[MAXCELLCHARS + VNAMESIZE + 2];
650  afs_int32 hosts[8];
651  int status = 0, pstatus;
652  struct hostent *h;
653
654  subs[0] = cell;
655  subs[1] = cellvol;
656
657  path = strdup(at->hostdir);
658  if (!path)
659    {
660      locker__error(context, "Out of memory getting zephyr subscriptions.\n");
661      return LOCKER_ENOMEM;
662    }
663
664  /* Walk down the path. At each level, add subscriptions for the cell,
665   * host, and volume where that path component lives.
666   */
667  p = path;
668  do
669    {
670      /* Move trailing NUL over one pathname component. */
671      *p = '/';
672      p = strchr(p + 1, '/');
673      if (p)
674        *p = '\0';
675
676      /* Get cell */
677      vio.in_size = 0;
678      vio.out = cell;
679      vio.out_size = sizeof(cell);
680      if (pioctl(path, VIOC_FILE_CELL_NAME, &vio, 1) != 0)
681        continue;
682
683      /* Get mountpoint name and generate cell:mountpoint. */
684      last_component = strrchr(path, '/');
685      if (last_component)
686        {
687          *last_component++ = '\0';
688          vio.in = last_component;
689        }
690      else
691        vio.in = "/";
692      vio.in_size = strlen(vio.in) + 1;
693      vio.out = vol;
694      vio.out_size = sizeof(vol);
695      pstatus = pioctl(path, VIOC_AFS_STAT_MT_PT, &vio, 1);
696      if (last_component)
697        *(last_component - 1) = '/';
698
699      if (pstatus != 0)
700        continue;
701
702      /* Get cell:volumname into cellvol, ignoring initial '#' or '%'. */
703      if (strchr(vol, ':'))
704        strcpy(cellvol, vol + 1);
705      else
706        sprintf(cellvol, "%s:%s", cell, vol + 1);
707
708      /* If there's only one site for this volume, add the hostname
709       * of the server to the subs list.
710       */
711      memset(hosts, 0, 2 * sizeof(*hosts));
712      vio.out = (caddr_t)hosts;
713      vio.out_size = sizeof(hosts);
714      if (pioctl(path, VIOCWHEREIS, &vio, 1) != 0)
715        continue;
716      if (!hosts[1])
717        {
718          h = gethostbyaddr((char *)&hosts[0], 4, AF_INET);
719          if (!h)
720            continue;
721          subs[2] = h->h_name;
722          status = locker__add_zsubs(context, subs, 3);
723        }
724      else
725        status = locker__add_zsubs(context, subs, 2);
726    }
727  while (status == LOCKER_SUCCESS && strlen(path) != strlen(at->hostdir));
728
729  free(path);
730  return status;
731}
732
733/* librxkad depends on this symbol in Transarc's des library, which we
734 * can't link with because of conflicts with our krb4 library. It never
735 * gets called though.
736 */
737void des_pcbc_init(void)
738{
739  abort();
740}
741
742static char *afs_realm_of_cell(context, cellconfig)
743     krb5_context context;
744     struct afsconf_cell *cellconfig;
745{
746  static char krbrlm[REALM_SZ+1];
747  char **hrealms = 0;
748
749  if (!cellconfig)
750    return 0;
751  if (krb5_get_host_realm(context, cellconfig->hostName[0], &hrealms))
752    return 0;
753  if (!hrealms[0])
754    return 0;
755  strcpy(krbrlm, hrealms[0]);
756
757  if (hrealms)
758    free(hrealms);
759
760  return krbrlm;
761}
762
763static int get_user_realm(krb5_context context, char *realm)
764{
765  krb5_principal client_principal = NULL;
766  krb5_ccache krb425_ccache = NULL;
767  krb5_error_code retval = 0;
768  int i;
769
770  retval = krb5_cc_default(context, &krb425_ccache);
771  if (retval)
772    goto fail;
773
774  retval = krb5_cc_get_principal(context, krb425_ccache, &client_principal);
775  if (retval)
776    goto fail;
777
778  i = krb5_princ_realm(context, client_principal)->length;
779  if (i > REALM_SZ - 1)
780    i = REALM_SZ - 1;
781  memcpy(realm, krb5_princ_realm(context, client_principal)->data, i);
782  realm[i] = '\0';
783
784fail:
785  if (krb425_ccache)
786    krb5_cc_close(context, krb425_ccache);
787  if (client_principal)
788    krb5_free_principal(context, client_principal);
789
790  return retval;
791}
Note: See TracBrowser for help on using the repository browser.