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