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