From 7fa33051506e155279f681148a0afa1eedd72429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Groenvall?= Date: Thu, 3 Apr 1997 13:10:17 +0000 Subject: [PATCH] Separate syscall functionality and kerberos convenience routines into afssys.c and afskrb.c. This to make it possible to use k_pioctl() without linking in all libraries in the world. git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@1544 ec53bebd-3082-4978-b11e-865c3cabbd6b --- lib/kafs/Makefile.in | 4 +- lib/kafs/afskrb.c | 408 +++++++++++++++++++++++++++++++++++++++++++ lib/kafs/afssys.c | 363 +------------------------------------- 3 files changed, 414 insertions(+), 361 deletions(-) create mode 100644 lib/kafs/afskrb.c diff --git a/lib/kafs/Makefile.in b/lib/kafs/Makefile.in index e93db0f8b..bbcd7b63a 100644 --- a/lib/kafs/Makefile.in +++ b/lib/kafs/Makefile.in @@ -31,9 +31,9 @@ SHARED = @SHARED@ AFS_EXTRA_LIBS = @AFS_EXTRA_LIBS@ LIB = $(LIBNAME).$(LIBEXT) $(AFS_EXTRA_LIBS) -SOURCES = afssys.c afslib.c +SOURCES = afssys.c afskrb.c afslib.c -OBJECTS = afssys.o +OBJECTS = afssys.o afskrb.o all: $(LIB) diff --git a/lib/kafs/afskrb.c b/lib/kafs/afskrb.c new file mode 100644 index 000000000..3d4af8db1 --- /dev/null +++ b/lib/kafs/afskrb.c @@ -0,0 +1,408 @@ +/* + * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" +#include "protos.h" + +RCSID("$Id$"); + +#include +#include +#include +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_SYS_FILIO_H +#include +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif + +#ifdef HAVE_ARPA_NAMESER_H +#include +#endif +#ifdef HAVE_RESOLV_H +#include +#endif + +#include +#include + +#include + +#include "afssysdefs.h" + +#define AUTH_SUPERUSER "afs" + +/* + * Here only ASCII characters are relevant. + */ + +#define IsAsciiLower(c) ('a' <= (c) && (c) <= 'z') + +#define ToAsciiUpper(c) ((c) - 'a' + 'A') + +static void +foldup(char *a, char *b) +{ + for (; *b; a++, b++) + if (IsAsciiLower(*b)) + *a = ToAsciiUpper(*b); + else + *a = *b; + *a = '\0'; +} + +static int +get_cred(char *princ, char *inst, char *krealm, CREDENTIALS *c, KTEXT_ST *tkt) +{ + int k_errno = krb_get_cred(princ, inst, krealm, c); + + if (k_errno != KSUCCESS) + { + k_errno = krb_mk_req(tkt, princ, inst, krealm, 0); + if (k_errno == KSUCCESS) + k_errno = krb_get_cred(princ, inst, krealm, c); + } + return k_errno; +} + + +/* Convert a string to a 32 bit ip number in network byte order. + Return 0 on error + */ + +static u_int32_t +ip_aton(char *ip) +{ + u_int32_t addr; + unsigned int a, b, c, d; + + if(sscanf(ip, "%u.%u.%u.%u", &a, &b, &c, &d) != 4) + return 0; + if((a | b | c | d) > 255) + return 0; + addr = (a << 24) | (b << 16) | (c << 8) | d; + addr = htonl(addr); + return addr; +} + +/* Try to get a db-server for an AFS cell from a AFSDB record */ + +static int +dns_find_cell(char *cell, char *dbserver) +{ + struct dns_reply *r; + int ok = -1; + r = dns_lookup(cell, "afsdb"); + if(r){ + struct resource_record *rr = r->head; + while(rr){ + if(rr->type == T_AFSDB && rr->u.afsdb->preference == 1){ + strncpy(dbserver, rr->u.afsdb->domain, MaxHostNameLen); + dbserver[MaxHostNameLen - 1] = 0; + ok = 0; + break; + } + rr = rr->next; + } + dns_free_data(r); + } + return ok; +} + + +/* Find the realm associated with cell. Do this by opening + /usr/vice/etc/CellServDB and getting the realm-of-host for the + first VL-server for the cell. + + This does not work when the VL-server is living in one cell, but + the cell it is serving is living in another cell. + */ + +static char* +realm_of_cell(char *cell) +{ + FILE *F; + char buf[1024]; + u_int32_t addr; + struct hostent *hp; + char *realm = NULL; + + F = fopen(_PATH_CELLSERVDB, "r"); + while(F && !feof(F)){ + fgets(buf, 1024, F); + if(buf[0] != '>') + continue; + if(strncmp(buf+1, cell, strlen(cell)) == 0){ + fgets(buf, 1024, F); + if(feof(F)) + break; + addr = ip_aton(buf); + if(addr == 0) + break; + hp = gethostbyaddr((char*)&addr, 4, AF_INET); + if(hp == NULL) + break; + strcpy(buf, hp->h_name); + realm = krb_realmofhost(buf); + break; + } + } + if(F) + fclose(F); + + if(realm == NULL){ + if(dns_find_cell(cell, buf) == 0) + realm = krb_realmofhost(buf); + } + return realm; +} + +/* + * Get tokens for all cells[] + */ +static int +k_afslog_cells(char *cells[], int max, char *krealm, uid_t uid) +{ + int err = KSUCCESS; + int i; + for(i = 0; i < max; i++) + err = k_afsklog_uid(cells[i], krealm, uid); + return err; +} + +/* + * Try to find the cells we should try to klog to in "file". + */ +static void +k_find_cells(char *file, char *cells[], int size, int *index) +{ + FILE *f; + char cell[64]; + int i; + f = fopen(file, "r"); + if (f == NULL) + return; + while (*index < size && fgets(cell, sizeof(cell), f)) { + char *nl = strchr(cell, '\n'); + if (nl) *nl = 0; + for(i = 0; i < *index; i++) + if(strcmp(cells[i], cell) == 0) + break; + if(i == *index) + cells[(*index)++] = strdup(cell); + } + fclose(f); +} + +static int +k_afsklog_all_local_cells(char *krealm, uid_t uid) +{ + int err; + char *cells[32]; /* XXX */ + int num_cells = sizeof(cells) / sizeof(cells[0]); + int index = 0; + + char *p, home[MaxPathLen]; + + if ((p = getenv("HOME"))) { + sprintf(home, "%s/.TheseCells", p); + k_find_cells(home, cells, num_cells, &index); + } + k_find_cells(_PATH_THESECELLS, cells, num_cells, &index); + k_find_cells(_PATH_THISCELL, cells, num_cells, &index); + + err = k_afslog_cells(cells, index, krealm, uid); + while(index > 0) + free(cells[--index]); + return err; +} + +int +k_afsklog_uid(char *cell, char *krealm, uid_t uid) +{ + int k_errno; + CREDENTIALS c; + KTEXT_ST ticket; + char realm[REALM_SZ]; + char *vl_realm; /* realm of vl-server */ + char *lrealm; /* local realm */ + char CELL[64]; + + if (cell == 0 || cell[0] == 0) + return k_afsklog_all_local_cells (krealm, uid); + foldup(CELL, cell); + + k_errno = krb_get_lrealm(realm , 0); + if(k_errno == KSUCCESS && (krealm == NULL || strcmp(krealm, realm))) + lrealm = realm; + else + lrealm = NULL; + + /* We're about to find the the realm that holds the key for afs in + * the specified cell. The problem is that null-instance + * afs-principals are common and that hitting the wrong realm might + * yield the wrong afs key. The following assumptions were made. + * + * Any realm passed to us is preferred. + * + * If there is a realm with the same name as the cell, it is most + * likely the correct realm to talk to. + * + * In most (maybe even all) cases the database servers of the cell + * will live in the realm we are looking for. + * + * Try the local realm, but if the previous cases fail, this is + * really a long shot. + * + */ + + /* comments on the ordering of these tests */ + + /* If the user passes a realm, she probably knows something we don't + * know and we should try afs@krealm (otherwise we're talking with a + * blondino and she might as well have it.) + */ + + k_errno = -1; + if(krealm){ + k_errno = get_cred(AUTH_SUPERUSER, cell, krealm, &c, &ticket); + if(k_errno) + k_errno = get_cred(AUTH_SUPERUSER, "", krealm, &c, &ticket); + } + + if(k_errno) + k_errno = get_cred(AUTH_SUPERUSER, cell, CELL, &c, &ticket); + if(k_errno) + k_errno = get_cred(AUTH_SUPERUSER, "", CELL, &c, &ticket); + + /* this might work in some conditions */ + if(k_errno && (vl_realm = realm_of_cell(cell))){ + k_errno = get_cred(AUTH_SUPERUSER, cell, vl_realm, &c, &ticket); + if(k_errno) + k_errno = get_cred(AUTH_SUPERUSER, "", vl_realm, &c, &ticket); + } + + if(k_errno && lrealm){ + k_errno = get_cred(AUTH_SUPERUSER, cell, lrealm, &c, &ticket); +#if 0 + /* this is most likely never right anyway, but won't fail */ + if(k_errno) + k_errno = get_cred(AUTH_SUPERUSER, "", lrealm, &c, &ticket); +#endif + } + + if (k_errno == KSUCCESS) + { + struct ViceIoctl parms; + struct ClearToken ct; + int32_t sizeof_x; + char buf[2048], *t; + + /* + * Build a struct ClearToken + */ + ct.AuthHandle = c.kvno; + memcpy (ct.HandShakeKey, c.session, sizeof(c.session)); + ct.ViceId = uid; /* is this always valid? */ + ct.BeginTimestamp = 1 + c.issue_date; + ct.EndTimestamp = krb_life_to_time(c.issue_date, c.lifetime); + + t = buf; + /* + * length of secret token followed by secret token + */ + sizeof_x = c.ticket_st.length; + memcpy(t, &sizeof_x, sizeof(sizeof_x)); + t += sizeof(sizeof_x); + memcpy(t, c.ticket_st.dat, sizeof_x); + t += sizeof_x; + /* + * length of clear token followed by clear token + */ + sizeof_x = sizeof(ct); + memcpy(t, &sizeof_x, sizeof(sizeof_x)); + t += sizeof(sizeof_x); + memcpy(t, &ct, sizeof_x); + t += sizeof_x; + + /* + * do *not* mark as primary cell + */ + sizeof_x = 0; + memcpy(t, &sizeof_x, sizeof(sizeof_x)); + t += sizeof(sizeof_x); + /* + * follow with cell name + */ + sizeof_x = strlen(cell) + 1; + memcpy(t, cell, sizeof_x); + t += sizeof_x; + + /* + * Build argument block + */ + parms.in = buf; + parms.in_size = t - buf; + parms.out = 0; + parms.out_size = 0; + k_pioctl(0, VIOCSETTOK, &parms, 0); + } + return k_errno; +} + +int +k_afsklog(char *cell, char *krealm) +{ + return k_afsklog_uid (cell, krealm, getuid()); +} diff --git a/lib/kafs/afssys.c b/lib/kafs/afssys.c index cf1f42cac..c4e949f20 100644 --- a/lib/kafs/afssys.c +++ b/lib/kafs/afssys.c @@ -41,24 +41,14 @@ RCSID("$Id$"); -#include -#include #include -#ifdef HAVE_SYS_TYPES_H -#include -#endif +#include +#include +#include + #ifdef HAVE_UNISTD_H #include #endif -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif #ifdef HAVE_SYS_IOCTL_H #include #endif @@ -69,152 +59,10 @@ RCSID("$Id$"); #include #endif -#include -#include -#include -#include - -#ifdef HAVE_ARPA_NAMESER_H -#include -#endif -#ifdef HAVE_RESOLV_H -#include -#endif - -#include #include -#include - #include "afssysdefs.h" -#define AUTH_SUPERUSER "afs" - -/* - * Here only ASCII characters are relevant. - */ - -#define IsAsciiLower(c) ('a' <= (c) && (c) <= 'z') - -#define ToAsciiUpper(c) ((c) - 'a' + 'A') - -static void -foldup(char *a, char *b) -{ - for (; *b; a++, b++) - if (IsAsciiLower(*b)) - *a = ToAsciiUpper(*b); - else - *a = *b; - *a = '\0'; -} - -static int -get_cred(char *princ, char *inst, char *krealm, CREDENTIALS *c, KTEXT_ST *tkt) -{ - int k_errno = krb_get_cred(princ, inst, krealm, c); - - if (k_errno != KSUCCESS) - { - k_errno = krb_mk_req(tkt, princ, inst, krealm, 0); - if (k_errno == KSUCCESS) - k_errno = krb_get_cred(princ, inst, krealm, c); - } - return k_errno; -} - - -/* Convert a string to a 32 bit ip number in network byte order. - Return 0 on error - */ - -static u_int32_t -ip_aton(char *ip) -{ - u_int32_t addr; - unsigned int a, b, c, d; - - if(sscanf(ip, "%u.%u.%u.%u", &a, &b, &c, &d) != 4) - return 0; - if((a | b | c | d) > 255) - return 0; - addr = (a << 24) | (b << 16) | (c << 8) | d; - addr = htonl(addr); - return addr; -} - -/* Try to get a db-server for an AFS cell from a AFSDB record */ - -static int -dns_find_cell(char *cell, char *dbserver) -{ - struct dns_reply *r; - int ok = -1; - r = dns_lookup(cell, "afsdb"); - if(r){ - struct resource_record *rr = r->head; - while(rr){ - if(rr->type == T_AFSDB && rr->u.afsdb->preference == 1){ - strncpy(dbserver, rr->u.afsdb->domain, MaxHostNameLen); - dbserver[MaxHostNameLen - 1] = 0; - ok = 0; - break; - } - rr = rr->next; - } - dns_free_data(r); - } - return ok; -} - - -/* Find the realm associated with cell. Do this by opening - /usr/vice/etc/CellServDB and getting the realm-of-host for the - first VL-server for the cell. - - This does not work when the VL-server is living in one cell, but - the cell it is serving is living in another cell. - */ - -static char* -realm_of_cell(char *cell) -{ - FILE *F; - char buf[1024]; - u_int32_t addr; - struct hostent *hp; - char *realm = NULL; - - F = fopen(_PATH_CELLSERVDB, "r"); - while(F && !feof(F)){ - fgets(buf, 1024, F); - if(buf[0] != '>') - continue; - if(strncmp(buf+1, cell, strlen(cell)) == 0){ - fgets(buf, 1024, F); - if(feof(F)) - break; - addr = ip_aton(buf); - if(addr == 0) - break; - hp = gethostbyaddr((char*)&addr, 4, AF_INET); - if(hp == NULL) - break; - strcpy(buf, hp->h_name); - realm = krb_realmofhost(buf); - break; - } - } - if(F) - fclose(F); - - if(realm == NULL){ - if(dns_find_cell(cell, buf) == 0) - realm = krb_realmofhost(buf); - } - return realm; -} - /* Magic to get AIX syscalls to work */ #ifdef _AIX @@ -261,208 +109,6 @@ aix_setup(void) } #endif - - -/* - * Get tokens for all cells[] - */ -static int -k_afslog_cells(char *cells[], int max, char *krealm, uid_t uid) -{ - int err = KSUCCESS; - int i; - for(i = 0; i < max; i++) - err = k_afsklog_uid(cells[i], krealm, uid); - return err; -} - -/* - * Try to find the cells we should try to klog to in "file". - */ -static void -k_find_cells(char *file, char *cells[], int size, int *index) -{ - FILE *f; - char cell[64]; - int i; - f = fopen(file, "r"); - if (f == NULL) - return; - while (*index < size && fgets(cell, sizeof(cell), f)) { - char *nl = strchr(cell, '\n'); - if (nl) *nl = 0; - for(i = 0; i < *index; i++) - if(strcmp(cells[i], cell) == 0) - break; - if(i == *index) - cells[(*index)++] = strdup(cell); - } - fclose(f); -} - -static int -k_afsklog_all_local_cells(char *krealm, uid_t uid) -{ - int err; - char *cells[32]; /* XXX */ - int num_cells = sizeof(cells) / sizeof(cells[0]); - int index = 0; - - char *p, home[MaxPathLen]; - - if ((p = getenv("HOME"))) { - sprintf(home, "%s/.TheseCells", p); - k_find_cells(home, cells, num_cells, &index); - } - k_find_cells(_PATH_THESECELLS, cells, num_cells, &index); - k_find_cells(_PATH_THISCELL, cells, num_cells, &index); - - err = k_afslog_cells(cells, index, krealm, uid); - while(index > 0) - free(cells[--index]); - return err; -} - -int -k_afsklog_uid(char *cell, char *krealm, uid_t uid) -{ - int k_errno; - CREDENTIALS c; - KTEXT_ST ticket; - char realm[REALM_SZ]; - char *vl_realm; /* realm of vl-server */ - char *lrealm; /* local realm */ - char CELL[64]; - - if (cell == 0 || cell[0] == 0) - return k_afsklog_all_local_cells (krealm, uid); - foldup(CELL, cell); - - k_errno = krb_get_lrealm(realm , 0); - if(k_errno == KSUCCESS && (krealm == NULL || strcmp(krealm, realm))) - lrealm = realm; - else - lrealm = NULL; - - /* We're about to find the the realm that holds the key for afs in - * the specified cell. The problem is that null-instance - * afs-principals are common and that hitting the wrong realm might - * yield the wrong afs key. The following assumptions were made. - * - * Any realm passed to us is preferred. - * - * If there is a realm with the same name as the cell, it is most - * likely the correct realm to talk to. - * - * In most (maybe even all) cases the database servers of the cell - * will live in the realm we are looking for. - * - * Try the local realm, but if the previous cases fail, this is - * really a long shot. - * - */ - - /* comments on the ordering of these tests */ - - /* If the user passes a realm, she probably knows something we don't - * know and we should try afs@krealm (otherwise we're talking with a - * blondino and she might as well have it.) - */ - - k_errno = -1; - if(krealm){ - k_errno = get_cred(AUTH_SUPERUSER, cell, krealm, &c, &ticket); - if(k_errno) - k_errno = get_cred(AUTH_SUPERUSER, "", krealm, &c, &ticket); - } - - if(k_errno) - k_errno = get_cred(AUTH_SUPERUSER, cell, CELL, &c, &ticket); - if(k_errno) - k_errno = get_cred(AUTH_SUPERUSER, "", CELL, &c, &ticket); - - /* this might work in some conditions */ - if(k_errno && (vl_realm = realm_of_cell(cell))){ - k_errno = get_cred(AUTH_SUPERUSER, cell, vl_realm, &c, &ticket); - if(k_errno) - k_errno = get_cred(AUTH_SUPERUSER, "", vl_realm, &c, &ticket); - } - - if(k_errno && lrealm){ - k_errno = get_cred(AUTH_SUPERUSER, cell, lrealm, &c, &ticket); -#if 0 - /* this is most likely never right anyway, but won't fail */ - if(k_errno) - k_errno = get_cred(AUTH_SUPERUSER, "", lrealm, &c, &ticket); -#endif - } - - if (k_errno == KSUCCESS) - { - struct ViceIoctl parms; - struct ClearToken ct; - int32_t sizeof_x; - char buf[2048], *t; - - /* - * Build a struct ClearToken - */ - ct.AuthHandle = c.kvno; - memcpy (ct.HandShakeKey, c.session, sizeof(c.session)); - ct.ViceId = uid; /* is this always valid? */ - ct.BeginTimestamp = 1 + c.issue_date; - ct.EndTimestamp = krb_life_to_time(c.issue_date, c.lifetime); - - t = buf; - /* - * length of secret token followed by secret token - */ - sizeof_x = c.ticket_st.length; - memcpy(t, &sizeof_x, sizeof(sizeof_x)); - t += sizeof(sizeof_x); - memcpy(t, c.ticket_st.dat, sizeof_x); - t += sizeof_x; - /* - * length of clear token followed by clear token - */ - sizeof_x = sizeof(ct); - memcpy(t, &sizeof_x, sizeof(sizeof_x)); - t += sizeof(sizeof_x); - memcpy(t, &ct, sizeof_x); - t += sizeof_x; - - /* - * do *not* mark as primary cell - */ - sizeof_x = 0; - memcpy(t, &sizeof_x, sizeof(sizeof_x)); - t += sizeof(sizeof_x); - /* - * follow with cell name - */ - sizeof_x = strlen(cell) + 1; - memcpy(t, cell, sizeof_x); - t += sizeof_x; - - /* - * Build argument block - */ - parms.in = buf; - parms.in_size = t - buf; - parms.out = 0; - parms.out_size = 0; - k_pioctl(0, VIOCSETTOK, &parms, 0); - } - return k_errno; -} - -int -k_afsklog(char *cell, char *krealm) -{ - return k_afsklog_uid (cell, krealm, getuid()); -} - - #define NO_ENTRY_POINT 0 #define SINGLE_ENTRY_POINT 1 #define MULTIPLE_ENTRY_POINT 2 @@ -681,4 +327,3 @@ k_hasafs(void) errno = saved_errno; return afs_entry_point != NO_ENTRY_POINT; } -