xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/kafs/common.c (revision d3273b5b76f5afaafe308cead5511dbb8df8c5e9)
1*d3273b5bSchristos /*	$NetBSD: common.c,v 1.2 2017/01/28 21:31:49 christos Exp $	*/
2ca1c9b0cSelric 
3ca1c9b0cSelric /*
4ca1c9b0cSelric  * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
5ca1c9b0cSelric  * (Royal Institute of Technology, Stockholm, Sweden).
6ca1c9b0cSelric  * All rights reserved.
7ca1c9b0cSelric  *
8ca1c9b0cSelric  * Redistribution and use in source and binary forms, with or without
9ca1c9b0cSelric  * modification, are permitted provided that the following conditions
10ca1c9b0cSelric  * are met:
11ca1c9b0cSelric  *
12ca1c9b0cSelric  * 1. Redistributions of source code must retain the above copyright
13ca1c9b0cSelric  *    notice, this list of conditions and the following disclaimer.
14ca1c9b0cSelric  *
15ca1c9b0cSelric  * 2. Redistributions in binary form must reproduce the above copyright
16ca1c9b0cSelric  *    notice, this list of conditions and the following disclaimer in the
17ca1c9b0cSelric  *    documentation and/or other materials provided with the distribution.
18ca1c9b0cSelric  *
19ca1c9b0cSelric  * 3. Neither the name of the Institute nor the names of its contributors
20ca1c9b0cSelric  *    may be used to endorse or promote products derived from this software
21ca1c9b0cSelric  *    without specific prior written permission.
22ca1c9b0cSelric  *
23ca1c9b0cSelric  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24ca1c9b0cSelric  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25ca1c9b0cSelric  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ca1c9b0cSelric  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27ca1c9b0cSelric  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28ca1c9b0cSelric  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29ca1c9b0cSelric  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30ca1c9b0cSelric  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31ca1c9b0cSelric  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32ca1c9b0cSelric  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33ca1c9b0cSelric  * SUCH DAMAGE.
34ca1c9b0cSelric  */
35ca1c9b0cSelric 
36ca1c9b0cSelric #include "kafs_locl.h"
37ca1c9b0cSelric 
38ca1c9b0cSelric #define AUTH_SUPERUSER "afs"
39ca1c9b0cSelric 
40ca1c9b0cSelric /*
41ca1c9b0cSelric  * Here only ASCII characters are relevant.
42ca1c9b0cSelric  */
43ca1c9b0cSelric 
44ca1c9b0cSelric #define IsAsciiLower(c) ('a' <= (c) && (c) <= 'z')
45ca1c9b0cSelric 
46ca1c9b0cSelric #define ToAsciiUpper(c) ((c) - 'a' + 'A')
47ca1c9b0cSelric 
48ca1c9b0cSelric static void (*kafs_verbose)(void *, const char *);
49ca1c9b0cSelric static void *kafs_verbose_ctx;
50ca1c9b0cSelric 
51ca1c9b0cSelric void
_kafs_foldup(char * a,const char * b)52ca1c9b0cSelric _kafs_foldup(char *a, const char *b)
53ca1c9b0cSelric {
54ca1c9b0cSelric   for (; *b; a++, b++)
55ca1c9b0cSelric     if (IsAsciiLower(*b))
56ca1c9b0cSelric       *a = ToAsciiUpper(*b);
57ca1c9b0cSelric     else
58ca1c9b0cSelric       *a = *b;
59ca1c9b0cSelric   *a = '\0';
60ca1c9b0cSelric }
61ca1c9b0cSelric 
62ca1c9b0cSelric void
kafs_set_verbose(void (* f)(void *,const char *),void * ctx)63ca1c9b0cSelric kafs_set_verbose(void (*f)(void *, const char *), void *ctx)
64ca1c9b0cSelric {
65ca1c9b0cSelric     if (f) {
66ca1c9b0cSelric 	kafs_verbose = f;
67ca1c9b0cSelric 	kafs_verbose_ctx = ctx;
68ca1c9b0cSelric     }
69ca1c9b0cSelric }
70ca1c9b0cSelric 
71ca1c9b0cSelric int
kafs_settoken_rxkad(const char * cell,struct ClearToken * ct,void * ticket,size_t ticket_len)72ca1c9b0cSelric kafs_settoken_rxkad(const char *cell, struct ClearToken *ct,
73ca1c9b0cSelric 		    void *ticket, size_t ticket_len)
74ca1c9b0cSelric {
75ca1c9b0cSelric     struct ViceIoctl parms;
76ca1c9b0cSelric     char buf[2048], *t;
77ca1c9b0cSelric     int32_t sizeof_x;
78ca1c9b0cSelric 
79ca1c9b0cSelric     t = buf;
80ca1c9b0cSelric     /*
81ca1c9b0cSelric      * length of secret token followed by secret token
82ca1c9b0cSelric      */
83ca1c9b0cSelric     sizeof_x = ticket_len;
84ca1c9b0cSelric     memcpy(t, &sizeof_x, sizeof(sizeof_x));
85ca1c9b0cSelric     t += sizeof(sizeof_x);
86ca1c9b0cSelric     memcpy(t, ticket, sizeof_x);
87ca1c9b0cSelric     t += sizeof_x;
88ca1c9b0cSelric     /*
89ca1c9b0cSelric      * length of clear token followed by clear token
90ca1c9b0cSelric      */
91ca1c9b0cSelric     sizeof_x = sizeof(*ct);
92ca1c9b0cSelric     memcpy(t, &sizeof_x, sizeof(sizeof_x));
93ca1c9b0cSelric     t += sizeof(sizeof_x);
94ca1c9b0cSelric     memcpy(t, ct, sizeof_x);
95ca1c9b0cSelric     t += sizeof_x;
96ca1c9b0cSelric 
97ca1c9b0cSelric     /*
98ca1c9b0cSelric      * do *not* mark as primary cell
99ca1c9b0cSelric      */
100ca1c9b0cSelric     sizeof_x = 0;
101ca1c9b0cSelric     memcpy(t, &sizeof_x, sizeof(sizeof_x));
102ca1c9b0cSelric     t += sizeof(sizeof_x);
103ca1c9b0cSelric     /*
104ca1c9b0cSelric      * follow with cell name
105ca1c9b0cSelric      */
106ca1c9b0cSelric     sizeof_x = strlen(cell) + 1;
107ca1c9b0cSelric     memcpy(t, cell, sizeof_x);
108ca1c9b0cSelric     t += sizeof_x;
109ca1c9b0cSelric 
110ca1c9b0cSelric     /*
111ca1c9b0cSelric      * Build argument block
112ca1c9b0cSelric      */
113ca1c9b0cSelric     parms.in = buf;
114ca1c9b0cSelric     parms.in_size = t - buf;
115ca1c9b0cSelric     parms.out = 0;
116ca1c9b0cSelric     parms.out_size = 0;
117ca1c9b0cSelric 
118ca1c9b0cSelric     return k_pioctl(0, VIOCSETTOK, &parms, 0);
119ca1c9b0cSelric }
120ca1c9b0cSelric 
121ca1c9b0cSelric void
_kafs_fixup_viceid(struct ClearToken * ct,uid_t uid)122ca1c9b0cSelric _kafs_fixup_viceid(struct ClearToken *ct, uid_t uid)
123ca1c9b0cSelric {
124ca1c9b0cSelric #define ODD(x) ((x) & 1)
125ca1c9b0cSelric     /* According to Transarc conventions ViceId is valid iff
126ca1c9b0cSelric      * (EndTimestamp - BeginTimestamp) is odd. By decrementing EndTime
127ca1c9b0cSelric      * the transformations:
128ca1c9b0cSelric      *
129ca1c9b0cSelric      * (issue_date, life) -> (StartTime, EndTime) -> (issue_date, life)
130ca1c9b0cSelric      * preserves the original values.
131ca1c9b0cSelric      */
132ca1c9b0cSelric     if (uid != 0)		/* valid ViceId */
133ca1c9b0cSelric     {
134ca1c9b0cSelric 	if (!ODD(ct->EndTimestamp - ct->BeginTimestamp))
135ca1c9b0cSelric 	    ct->EndTimestamp--;
136ca1c9b0cSelric     }
137ca1c9b0cSelric     else			/* not valid ViceId */
138ca1c9b0cSelric     {
139ca1c9b0cSelric 	if (ODD(ct->EndTimestamp - ct->BeginTimestamp))
140ca1c9b0cSelric 	    ct->EndTimestamp--;
141ca1c9b0cSelric     }
142ca1c9b0cSelric }
143ca1c9b0cSelric 
144ca1c9b0cSelric /* Try to get a db-server for an AFS cell from a AFSDB record */
145ca1c9b0cSelric 
146ca1c9b0cSelric static int
dns_find_cell(const char * cell,char * dbserver,size_t len)147ca1c9b0cSelric dns_find_cell(const char *cell, char *dbserver, size_t len)
148ca1c9b0cSelric {
149ca1c9b0cSelric     struct rk_dns_reply *r;
150ca1c9b0cSelric     int ok = -1;
151ca1c9b0cSelric     r = rk_dns_lookup(cell, "afsdb");
152ca1c9b0cSelric     if(r){
153ca1c9b0cSelric 	struct rk_resource_record *rr = r->head;
154ca1c9b0cSelric 	while(rr){
155ca1c9b0cSelric 	    if(rr->type == rk_ns_t_afsdb && rr->u.afsdb->preference == 1){
156ca1c9b0cSelric 		strlcpy(dbserver,
157ca1c9b0cSelric 				rr->u.afsdb->domain,
158ca1c9b0cSelric 				len);
159ca1c9b0cSelric 		ok = 0;
160ca1c9b0cSelric 		break;
161ca1c9b0cSelric 	    }
162ca1c9b0cSelric 	    rr = rr->next;
163ca1c9b0cSelric 	}
164ca1c9b0cSelric 	rk_dns_free_data(r);
165ca1c9b0cSelric     }
166ca1c9b0cSelric     return ok;
167ca1c9b0cSelric }
168ca1c9b0cSelric 
169ca1c9b0cSelric 
170ca1c9b0cSelric /*
171ca1c9b0cSelric  * Try to find the cells we should try to klog to in "file".
172ca1c9b0cSelric  */
173ca1c9b0cSelric static void
find_cells(const char * file,char *** cells,int * idx)174ca1c9b0cSelric find_cells(const char *file, char ***cells, int *idx)
175ca1c9b0cSelric {
176ca1c9b0cSelric     FILE *f;
177ca1c9b0cSelric     char cell[64];
178ca1c9b0cSelric     int i;
179ca1c9b0cSelric     int ind = *idx;
180ca1c9b0cSelric 
181ca1c9b0cSelric     f = fopen(file, "r");
182ca1c9b0cSelric     if (f == NULL)
183ca1c9b0cSelric 	return;
184ca1c9b0cSelric     while (fgets(cell, sizeof(cell), f)) {
185ca1c9b0cSelric 	char *t;
186ca1c9b0cSelric 	t = cell + strlen(cell);
187ca1c9b0cSelric 	for (; t >= cell; t--)
188ca1c9b0cSelric 	  if (*t == '\n' || *t == '\t' || *t == ' ')
189ca1c9b0cSelric 	    *t = 0;
190ca1c9b0cSelric 	if (cell[0] == '\0' || cell[0] == '#')
191ca1c9b0cSelric 	    continue;
192ca1c9b0cSelric 	for(i = 0; i < ind; i++)
193ca1c9b0cSelric 	    if(strcmp((*cells)[i], cell) == 0)
194ca1c9b0cSelric 		break;
195ca1c9b0cSelric 	if(i == ind){
196ca1c9b0cSelric 	    char **tmp;
197ca1c9b0cSelric 
198ca1c9b0cSelric 	    tmp = realloc(*cells, (ind + 1) * sizeof(**cells));
199ca1c9b0cSelric 	    if (tmp == NULL)
200ca1c9b0cSelric 		break;
201ca1c9b0cSelric 	    *cells = tmp;
202ca1c9b0cSelric 	    (*cells)[ind] = strdup(cell);
203ca1c9b0cSelric 	    if ((*cells)[ind] == NULL)
204ca1c9b0cSelric 		break;
205ca1c9b0cSelric 	    ++ind;
206ca1c9b0cSelric 	}
207ca1c9b0cSelric     }
208ca1c9b0cSelric     fclose(f);
209ca1c9b0cSelric     *idx = ind;
210ca1c9b0cSelric }
211ca1c9b0cSelric 
212ca1c9b0cSelric /*
213ca1c9b0cSelric  * Get tokens for all cells[]
214ca1c9b0cSelric  */
215ca1c9b0cSelric static int
afslog_cells(struct kafs_data * data,char ** cells,int max,uid_t uid,const char * homedir)216ca1c9b0cSelric afslog_cells(struct kafs_data *data, char **cells, int max, uid_t uid,
217ca1c9b0cSelric 	     const char *homedir)
218ca1c9b0cSelric {
219ca1c9b0cSelric     int ret = 0;
220ca1c9b0cSelric     int i;
221ca1c9b0cSelric     for (i = 0; i < max; i++) {
222ca1c9b0cSelric         int er = (*data->afslog_uid)(data, cells[i], 0, uid, homedir);
223ca1c9b0cSelric 	if (er)
224ca1c9b0cSelric 	    ret = er;
225ca1c9b0cSelric     }
226ca1c9b0cSelric     return ret;
227ca1c9b0cSelric }
228ca1c9b0cSelric 
229ca1c9b0cSelric int
_kafs_afslog_all_local_cells(struct kafs_data * data,uid_t uid,const char * homedir)230ca1c9b0cSelric _kafs_afslog_all_local_cells(struct kafs_data *data,
231ca1c9b0cSelric 			     uid_t uid, const char *homedir)
232ca1c9b0cSelric {
233ca1c9b0cSelric     int ret;
234ca1c9b0cSelric     char **cells = NULL;
235ca1c9b0cSelric     int idx = 0;
236ca1c9b0cSelric 
237ca1c9b0cSelric     if (homedir == NULL)
238ca1c9b0cSelric 	homedir = getenv("HOME");
239ca1c9b0cSelric     if (homedir != NULL) {
240ca1c9b0cSelric 	char home[MaxPathLen];
241ca1c9b0cSelric 	snprintf(home, sizeof(home), "%s/.TheseCells", homedir);
242ca1c9b0cSelric 	find_cells(home, &cells, &idx);
243ca1c9b0cSelric     }
244ca1c9b0cSelric     find_cells(_PATH_THESECELLS, &cells, &idx);
245ca1c9b0cSelric     find_cells(_PATH_THISCELL, &cells, &idx);
246ca1c9b0cSelric     find_cells(_PATH_ARLA_THESECELLS, &cells, &idx);
247ca1c9b0cSelric     find_cells(_PATH_ARLA_THISCELL, &cells, &idx);
248ca1c9b0cSelric     find_cells(_PATH_OPENAFS_DEBIAN_THESECELLS, &cells, &idx);
249ca1c9b0cSelric     find_cells(_PATH_OPENAFS_DEBIAN_THISCELL, &cells, &idx);
250ca1c9b0cSelric     find_cells(_PATH_OPENAFS_MACOSX_THESECELLS, &cells, &idx);
251ca1c9b0cSelric     find_cells(_PATH_OPENAFS_MACOSX_THISCELL, &cells, &idx);
252ca1c9b0cSelric     find_cells(_PATH_ARLA_DEBIAN_THESECELLS, &cells, &idx);
253ca1c9b0cSelric     find_cells(_PATH_ARLA_DEBIAN_THISCELL, &cells, &idx);
254ca1c9b0cSelric     find_cells(_PATH_ARLA_OPENBSD_THESECELLS, &cells, &idx);
255ca1c9b0cSelric     find_cells(_PATH_ARLA_OPENBSD_THISCELL, &cells, &idx);
256ca1c9b0cSelric 
257ca1c9b0cSelric     ret = afslog_cells(data, cells, idx, uid, homedir);
258ca1c9b0cSelric     while(idx > 0)
259ca1c9b0cSelric 	free(cells[--idx]);
260ca1c9b0cSelric     free(cells);
261ca1c9b0cSelric     return ret;
262ca1c9b0cSelric }
263ca1c9b0cSelric 
264ca1c9b0cSelric 
265ca1c9b0cSelric static int
file_find_cell(struct kafs_data * data,const char * cell,char ** realm,int exact)266ca1c9b0cSelric file_find_cell(struct kafs_data *data,
267ca1c9b0cSelric 	       const char *cell, char **realm, int exact)
268ca1c9b0cSelric {
269ca1c9b0cSelric     FILE *F;
270ca1c9b0cSelric     char buf[1024];
271ca1c9b0cSelric     char *p;
272ca1c9b0cSelric     int ret = -1;
273ca1c9b0cSelric 
274ca1c9b0cSelric     if ((F = fopen(_PATH_CELLSERVDB, "r"))
275ca1c9b0cSelric 	|| (F = fopen(_PATH_ARLA_CELLSERVDB, "r"))
276ca1c9b0cSelric 	|| (F = fopen(_PATH_OPENAFS_DEBIAN_CELLSERVDB, "r"))
277ca1c9b0cSelric 	|| (F = fopen(_PATH_OPENAFS_MACOSX_CELLSERVDB, "r"))
278ca1c9b0cSelric 	|| (F = fopen(_PATH_ARLA_DEBIAN_CELLSERVDB, "r"))) {
279ca1c9b0cSelric 	while (fgets(buf, sizeof(buf), F)) {
280ca1c9b0cSelric 	    int cmp;
281ca1c9b0cSelric 
282ca1c9b0cSelric 	    if (buf[0] != '>')
283ca1c9b0cSelric 		continue; /* Not a cell name line, try next line */
284ca1c9b0cSelric 	    p = buf;
285ca1c9b0cSelric 	    strsep(&p, " \t\n#");
286ca1c9b0cSelric 
287ca1c9b0cSelric 	    if (exact)
288ca1c9b0cSelric 		cmp = strcmp(buf + 1, cell);
289ca1c9b0cSelric 	    else
290ca1c9b0cSelric 		cmp = strncmp(buf + 1, cell, strlen(cell));
291ca1c9b0cSelric 
292ca1c9b0cSelric 	    if (cmp == 0) {
293ca1c9b0cSelric 		/*
294ca1c9b0cSelric 		 * We found the cell name we're looking for.
295ca1c9b0cSelric 		 * Read next line on the form ip-address '#' hostname
296ca1c9b0cSelric 		 */
297ca1c9b0cSelric 		if (fgets(buf, sizeof(buf), F) == NULL)
298ca1c9b0cSelric 		    break;	/* Read failed, give up */
299ca1c9b0cSelric 		p = strchr(buf, '#');
300ca1c9b0cSelric 		if (p == NULL)
301ca1c9b0cSelric 		    break;	/* No '#', give up */
302ca1c9b0cSelric 		p++;
303ca1c9b0cSelric 		if (buf[strlen(buf) - 1] == '\n')
304ca1c9b0cSelric 		    buf[strlen(buf) - 1] = '\0';
305ca1c9b0cSelric 		*realm = (*data->get_realm)(data, p);
306ca1c9b0cSelric 		if (*realm && **realm != '\0')
307ca1c9b0cSelric 		    ret = 0;
308ca1c9b0cSelric 		break;		/* Won't try any more */
309ca1c9b0cSelric 	    }
310ca1c9b0cSelric 	}
311ca1c9b0cSelric 	fclose(F);
312ca1c9b0cSelric     }
313ca1c9b0cSelric     return ret;
314ca1c9b0cSelric }
315ca1c9b0cSelric 
316ca1c9b0cSelric /* Find the realm associated with cell. Do this by opening CellServDB
317ca1c9b0cSelric    file and getting the realm-of-host for the first VL-server for the
318ca1c9b0cSelric    cell.
319ca1c9b0cSelric 
320ca1c9b0cSelric    This does not work when the VL-server is living in one realm, but
321ca1c9b0cSelric    the cell it is serving is living in another realm.
322ca1c9b0cSelric 
323ca1c9b0cSelric    Return 0 on success, -1 otherwise.
324ca1c9b0cSelric    */
325ca1c9b0cSelric 
326ca1c9b0cSelric int
_kafs_realm_of_cell(struct kafs_data * data,const char * cell,char ** realm)327ca1c9b0cSelric _kafs_realm_of_cell(struct kafs_data *data,
328ca1c9b0cSelric 		    const char *cell, char **realm)
329ca1c9b0cSelric {
330ca1c9b0cSelric     char buf[1024];
331ca1c9b0cSelric     int ret;
332ca1c9b0cSelric 
333ca1c9b0cSelric     ret = file_find_cell(data, cell, realm, 1);
334ca1c9b0cSelric     if (ret == 0)
335ca1c9b0cSelric 	return ret;
336ca1c9b0cSelric     if (dns_find_cell(cell, buf, sizeof(buf)) == 0) {
337ca1c9b0cSelric 	*realm = (*data->get_realm)(data, buf);
338ca1c9b0cSelric 	if(*realm != NULL)
339ca1c9b0cSelric 	    return 0;
340ca1c9b0cSelric     }
341ca1c9b0cSelric     return file_find_cell(data, cell, realm, 0);
342ca1c9b0cSelric }
343ca1c9b0cSelric 
344ca1c9b0cSelric static int
_kafs_try_get_cred(struct kafs_data * data,const char * user,const char * cell,const char * realm,uid_t uid,struct kafs_token * kt)345ca1c9b0cSelric _kafs_try_get_cred(struct kafs_data *data, const char *user, const char *cell,
346ca1c9b0cSelric 		   const char *realm, uid_t uid, struct kafs_token *kt)
347ca1c9b0cSelric {
348ca1c9b0cSelric     int ret;
349ca1c9b0cSelric 
350ca1c9b0cSelric     ret = (*data->get_cred)(data, user, cell, realm, uid, kt);
351ca1c9b0cSelric     if (kafs_verbose) {
352ca1c9b0cSelric 	const char *estr = (*data->get_error)(data, ret);
353ca1c9b0cSelric 	char *str;
354b9d004c6Schristos 	int aret;
355b9d004c6Schristos 
356b9d004c6Schristos 	aret = asprintf(&str, "%s tried afs%s%s@%s -> %s (%d)",
357ca1c9b0cSelric 			data->name, cell ? "/" : "",
358ca1c9b0cSelric 			cell ? cell : "", realm, estr ? estr : "unknown", ret);
359b9d004c6Schristos 	if (aret != -1) {
360ca1c9b0cSelric 	    (*kafs_verbose)(kafs_verbose_ctx, str);
361b9d004c6Schristos 	    free(str);
362b9d004c6Schristos 	} else {
363b9d004c6Schristos 	    (*kafs_verbose)(kafs_verbose_ctx, "out of memory");
364b9d004c6Schristos 	}
365ca1c9b0cSelric 	if (estr)
366ca1c9b0cSelric 	    (*data->free_error)(data, estr);
367ca1c9b0cSelric     }
368ca1c9b0cSelric 
369ca1c9b0cSelric     return ret;
370ca1c9b0cSelric }
371ca1c9b0cSelric 
372ca1c9b0cSelric 
373ca1c9b0cSelric int
_kafs_get_cred(struct kafs_data * data,const char * cell,const char * realm_hint,const char * realm,uid_t uid,struct kafs_token * kt)374ca1c9b0cSelric _kafs_get_cred(struct kafs_data *data,
375ca1c9b0cSelric 	       const char *cell,
376ca1c9b0cSelric 	       const char *realm_hint,
377ca1c9b0cSelric 	       const char *realm,
378ca1c9b0cSelric 	       uid_t uid,
379ca1c9b0cSelric 	       struct kafs_token *kt)
380ca1c9b0cSelric {
381ca1c9b0cSelric     int ret = -1;
382ca1c9b0cSelric     char *vl_realm;
383ca1c9b0cSelric     char CELL[64];
384ca1c9b0cSelric 
385ca1c9b0cSelric     /* We're about to find the realm that holds the key for afs in
386ca1c9b0cSelric      * the specified cell. The problem is that null-instance
387ca1c9b0cSelric      * afs-principals are common and that hitting the wrong realm might
388ca1c9b0cSelric      * yield the wrong afs key. The following assumptions were made.
389ca1c9b0cSelric      *
390ca1c9b0cSelric      * Any realm passed to us is preferred.
391ca1c9b0cSelric      *
392ca1c9b0cSelric      * If there is a realm with the same name as the cell, it is most
393ca1c9b0cSelric      * likely the correct realm to talk to.
394ca1c9b0cSelric      *
395ca1c9b0cSelric      * In most (maybe even all) cases the database servers of the cell
396ca1c9b0cSelric      * will live in the realm we are looking for.
397ca1c9b0cSelric      *
398ca1c9b0cSelric      * Try the local realm, but if the previous cases fail, this is
399ca1c9b0cSelric      * really a long shot.
400ca1c9b0cSelric      *
401ca1c9b0cSelric      */
402ca1c9b0cSelric 
403ca1c9b0cSelric     /* comments on the ordering of these tests */
404ca1c9b0cSelric 
405ca1c9b0cSelric     /* If the user passes a realm, she probably knows something we don't
406ca1c9b0cSelric      * know and we should try afs@realm_hint.
407ca1c9b0cSelric      */
408ca1c9b0cSelric 
409ca1c9b0cSelric     if (realm_hint) {
410ca1c9b0cSelric 	ret = _kafs_try_get_cred(data, AUTH_SUPERUSER,
411ca1c9b0cSelric 				 cell, realm_hint, uid, kt);
412ca1c9b0cSelric 	if (ret == 0) return 0;
413ca1c9b0cSelric 	ret = _kafs_try_get_cred(data, AUTH_SUPERUSER,
414ca1c9b0cSelric 				 NULL, realm_hint, uid, kt);
415ca1c9b0cSelric 	if (ret == 0) return 0;
416ca1c9b0cSelric     }
417ca1c9b0cSelric 
418ca1c9b0cSelric     _kafs_foldup(CELL, cell);
419ca1c9b0cSelric 
420ca1c9b0cSelric     /*
421ca1c9b0cSelric      * If the AFS servers have a file /usr/afs/etc/krb.conf containing
422ca1c9b0cSelric      * REALM we still don't have to resort to cross-cell authentication.
423ca1c9b0cSelric      * Try afs.cell@REALM.
424ca1c9b0cSelric      */
425ca1c9b0cSelric     ret = _kafs_try_get_cred(data, AUTH_SUPERUSER,
426ca1c9b0cSelric 			     cell, realm, uid, kt);
427ca1c9b0cSelric     if (ret == 0) return 0;
428ca1c9b0cSelric 
429ca1c9b0cSelric     /*
430ca1c9b0cSelric      * If cell == realm we don't need no cross-cell authentication.
431ca1c9b0cSelric      * Try afs@REALM.
432ca1c9b0cSelric      */
433ca1c9b0cSelric     if (strcmp(CELL, realm) == 0) {
434ca1c9b0cSelric         ret = _kafs_try_get_cred(data, AUTH_SUPERUSER,
435ca1c9b0cSelric 				 NULL, realm, uid, kt);
436ca1c9b0cSelric 	if (ret == 0) return 0;
437ca1c9b0cSelric     }
438ca1c9b0cSelric 
439ca1c9b0cSelric     /*
440ca1c9b0cSelric      * We failed to get ``first class tickets'' for afs,
441ca1c9b0cSelric      * fall back to cross-cell authentication.
442ca1c9b0cSelric      * Try afs@CELL.
443ca1c9b0cSelric      * Try afs.cell@CELL.
444ca1c9b0cSelric      */
445ca1c9b0cSelric     ret = _kafs_try_get_cred(data, AUTH_SUPERUSER,
446ca1c9b0cSelric 			     NULL, CELL, uid, kt);
447ca1c9b0cSelric     if (ret == 0) return 0;
448ca1c9b0cSelric     ret = _kafs_try_get_cred(data, AUTH_SUPERUSER,
449ca1c9b0cSelric 			     cell, CELL, uid, kt);
450ca1c9b0cSelric     if (ret == 0) return 0;
451ca1c9b0cSelric 
452ca1c9b0cSelric     /*
453ca1c9b0cSelric      * Perhaps the cell doesn't correspond to any realm?
454ca1c9b0cSelric      * Use realm of first volume location DB server.
455ca1c9b0cSelric      * Try afs.cell@VL_REALM.
456ca1c9b0cSelric      * Try afs@VL_REALM???
457ca1c9b0cSelric      */
458ca1c9b0cSelric     if (_kafs_realm_of_cell(data, cell, &vl_realm) == 0
459ca1c9b0cSelric 	&& strcmp(vl_realm, realm) != 0
460ca1c9b0cSelric 	&& strcmp(vl_realm, CELL) != 0) {
461ca1c9b0cSelric 	ret = _kafs_try_get_cred(data, AUTH_SUPERUSER,
462ca1c9b0cSelric 				 cell, vl_realm, uid, kt);
463ca1c9b0cSelric 	if (ret)
464ca1c9b0cSelric 	    ret = _kafs_try_get_cred(data, AUTH_SUPERUSER,
465ca1c9b0cSelric 				     NULL, vl_realm, uid, kt);
466ca1c9b0cSelric 	free(vl_realm);
467ca1c9b0cSelric 	if (ret == 0) return 0;
468ca1c9b0cSelric     }
469ca1c9b0cSelric 
470ca1c9b0cSelric     return ret;
471ca1c9b0cSelric }
472