Annotation of 43BSDTahoe/new/sunrpc/svc_auth_unix.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
                      3:  * unrestricted use provided that this legend is included on all tape
                      4:  * media and as a part of the software program in whole or part.  Users
                      5:  * may copy or modify Sun RPC without charge, but are not authorized
                      6:  * to license or distribute it to anyone else except as part of a product or
                      7:  * program developed by the user.
                      8:  * 
                      9:  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
                     10:  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
                     11:  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
                     12:  * 
                     13:  * Sun RPC is provided with no support and without any obligation on the
                     14:  * part of Sun Microsystems, Inc. to assist in its use, correction,
                     15:  * modification or enhancement.
                     16:  * 
                     17:  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
                     18:  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
                     19:  * OR ANY PART THEREOF.
                     20:  * 
                     21:  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
                     22:  * or profits or other special, indirect and consequential damages, even if
                     23:  * Sun has been advised of the possibility of such damages.
                     24:  * 
                     25:  * Sun Microsystems, Inc.
                     26:  * 2550 Garcia Avenue
                     27:  * Mountain View, California  94043
                     28:  */
                     29: #ifndef lint
                     30: static char sccsid[] = "@(#)svc_auth_unix.c 1.4 85/03/14 Copyr 1984 Sun Micro";
                     31: #endif
                     32: 
                     33: /*
                     34:  * svc_auth_unix.c
                     35:  * Handles UNIX flavor authentication parameters on the service side of rpc.
                     36:  * There are two svc auth implementations here: AUTH_UNIX and AUTH_SHORT.
                     37:  * _svcauth_unix does full blown unix style uid,gid+gids auth,
                     38:  * _svcauth_short uses a shorthand auth to index into a cache of longhand auths.
                     39:  *
                     40:  * Copyright (C) 1984, Sun Microsystems, Inc.
                     41:  */
                     42: 
                     43: #include <stdio.h>
                     44: #include "types.h"
                     45: #include <sys/time.h>
                     46: #include <netinet/in.h>
                     47: #include "xdr.h"
                     48: #include "auth.h"
                     49: #include "clnt.h"
                     50: #include "rpc_msg.h"
                     51: #include "svc.h"
                     52: #include "auth_unix.h"
                     53: #include "svc_auth.h"
                     54: char *mem_alloc();
                     55: 
                     56: #define SHORT_VERF_SIZE (3 * BYTES_PER_XDR_UNIT)
                     57: #define CACHE_SIZE 16
                     58: 
                     59: static struct cache_entry {
                     60:        u_long          sh;             /* short hand value */
                     61: #define SHORT_CRED_SIZE (sizeof (u_long))
                     62:        short           cred_len;       /* byte length of opaque credential */
                     63:        caddr_t         cred_base;      /* the opaque credential body */
                     64:        struct authunix_parms aup;      /* cooked, deserialized credentials */
                     65: } cache[CACHE_SIZE];
                     66: 
                     67: static short cacheindex[CACHE_SIZE];
                     68: 
                     69: /*
                     70:  * Cache handling macros
                     71:  */
                     72: #define valid_aup(aup) (TRUE)
                     73: #define nexti(i)  ((i == CACHE_SIZE-1) ? 0 : i+1)
                     74: #define previ(i)  ((i == 0) ? CACHE_SIZE-1 : i-1)
                     75: #define cache_hit(c, d) \
                     76:    ( hits++, d=cnt-c, depth += d, maxdepth = (d > maxdepth) ? d: maxdepth )
                     77: 
                     78: /*
                     79:  * Cache handling routines
                     80:  */
                     81: static short   find_short_hand();
                     82: static short   find_long_hand();
                     83: 
                     84: /*
                     85:  * Cache variables
                     86:  */
                     87: static short head, maxdepth;   /* values from 0 to CACHE_SIZE-1, inclusive */
                     88: static short cnt;              /*  values from 0 to CACHE_SIZE, inclusive */
                     89: static u_long additions, deletions, queries, hits, depth;
                     90: static struct timeval last_time;
                     91: static inited = 0;             /* stupid kludge to be sure init gets called */
                     92: 
                     93: 
                     94: /*
                     95:  * Unix longhand authenticator
                     96:  */
                     97: enum auth_stat
                     98: _svcauth_unix(rqst, msg)
                     99:        register struct svc_req *rqst;
                    100:        register struct rpc_msg *msg;
                    101: {
                    102:        register short i = -1;
                    103:        register int len = msg->rm_call.cb_cred.oa_length;
                    104:        register caddr_t base = msg->rm_call.cb_cred.oa_base;
                    105:        register enum auth_stat stat = AUTH_OK;
                    106:        XDR xdrs;
                    107:        struct authunix_parms aup;
                    108:        struct opaque_auth short_cred;
                    109: 
                    110:        if (!inited) {
                    111:                svcauth_unix_init();
                    112:        }
                    113:        while ((i = find_long_hand(base, len)) < 0) {
                    114:                /* deserialize credentials */
                    115:                aup.aup_machname = NULL;
                    116:                aup.aup_gids = (int *)NULL;
                    117:                xdrmem_create(&xdrs, base, (u_int)len, XDR_DECODE); 
                    118:                if (! (xdr_authunix_parms(&xdrs, &aup) && valid_aup(&aup))) {
                    119:                        xdrs.x_op = XDR_FREE;
                    120:                        (void)xdr_authunix_parms(&xdrs, &aup);
                    121:                        stat = AUTH_BADCRED;
                    122:                        goto done;
                    123:                }
                    124:                /* now make a new cache entry for this credential */
                    125:                cache_new_user(base, len, &aup);
                    126:        }
                    127:        rqst->rq_clntcred = (caddr_t)&(cache[i].aup);
                    128:        /* now build a verifier that suggests using the short hand credential */
                    129:        short_cred.oa_flavor = AUTH_SHORT;
                    130:        short_cred.oa_length = SHORT_CRED_SIZE;
                    131:        short_cred.oa_base = (caddr_t)&(cache[i].sh);
                    132:        /* the short hand cred get serialized into a verifier */
                    133:        xdrmem_create(&xdrs, rqst->rq_xprt->xp_verf.oa_base,
                    134:            SHORT_VERF_SIZE, XDR_ENCODE);
                    135:        if (! xdr_opaque_auth(&xdrs, &short_cred)) {
                    136:                stat = AUTH_BADCRED;
                    137:                goto done;
                    138:        }
                    139:        rqst->rq_xprt->xp_verf.oa_length = XDR_GETPOS(&xdrs);
                    140:        rqst->rq_xprt->xp_verf.oa_flavor = AUTH_SHORT;
                    141: done:
                    142:        XDR_DESTROY(&xdrs);
                    143:        return (stat);
                    144: }
                    145: 
                    146: 
                    147: /*
                    148:  * Shorthand unix authenticator
                    149:  * Looks up longhand in a cache.
                    150:  */
                    151: enum auth_stat 
                    152: _svcauth_short(rqst, msg)
                    153:        struct svc_req *rqst;
                    154:        struct rpc_msg *msg;
                    155: {
                    156:        short i;
                    157: 
                    158:        if (!inited) {
                    159:                svcauth_unix_init();
                    160:        }
                    161:        if (msg->rm_call.cb_cred.oa_length != SHORT_CRED_SIZE)
                    162:                return (AUTH_BADCRED);
                    163:        if ((i = find_short_hand(*(u_long *)msg->rm_call.cb_cred.oa_base)) < 0)
                    164:                return (AUTH_REJECTEDCRED);
                    165:        rqst->rq_clntcred = (caddr_t)&(cache[i].aup);
                    166:        return (AUTH_OK);
                    167: }
                    168: 
                    169: 
                    170: /*
                    171:  * returns cache index or -1 if sh not in the cache
                    172:  */
                    173: static short
                    174: find_short_hand(sh)
                    175:        register u_long sh;  /* short hand value */
                    176: {
                    177:        /* declared in order of importance */
                    178:        register short entry, i, c, p;
                    179: 
                    180:        queries++;
                    181:        for (c = cnt, i = head; c > 0; --c, i = nexti(i)) {
                    182: 
                    183:                entry = cacheindex[i];
                    184:                if (sh == cache[entry].sh) {
                    185:                        /* cache hit! Now buble swap i up one notch */
                    186:                        cache_hit(c, p);  /* used for accounting only */
                    187:                        if (i != head) {
                    188:                                /* c acts as the temporary variable */
                    189:                                p = previ(i);
                    190:                                c = cacheindex[p];
                    191:                                cacheindex[p] = entry; /* gets cacheindex[i] */
                    192:                                cacheindex[i] = c;
                    193:                        }
                    194:                        return (entry);
                    195:                }  /* end of successful cache hit */
                    196:        }
                    197:        return (-1);
                    198: }
                    199: 
                    200: /*
                    201:  * returns cache index or -1 if cred not in the cache
                    202:  */
                    203: static short
                    204: find_long_hand(cred_base, len)
                    205:        register caddr_t cred_base;
                    206:        register int len;
                    207: {
                    208:        /* declared in order of importance */
                    209:        register short entry, i, c, p;
                    210: 
                    211:        queries++;
                    212:        for (c = cnt, i = head; c > 0; --c, i = nexti(i)) {
                    213: 
                    214:                entry = cacheindex[i];
                    215:                if ((cache[entry].cred_len == len) &&
                    216:                    (bcmp(cache[entry].cred_base, cred_base, len) == 0)) {
                    217:                        /* cache hit! Now buble swap i up one notch */
                    218:                        cache_hit(c, p);  /* used for accounting only */
                    219:                        if (i != head) {
                    220:                                /* c acts as the temporary variable */
                    221:                                p = previ(i);
                    222:                                c = cacheindex[p];
                    223:                                cacheindex[p] = entry; /* gets cacheindex[i] */
                    224:                                cacheindex[i] = c;
                    225:                        }
                    226:                return (entry);
                    227:                }  /* end of successful cache hit */
                    228:        }
                    229:        return (-1);
                    230: }
                    231: 
                    232: /*
                    233:  * Place a new entry at the HEAD of the cache.  This means moving the
                    234:  * heap index back one and possibly flushing the oldest entry from the cache.
                    235:  */
                    236: static
                    237: cache_new_user(base, len, aup)
                    238:        caddr_t base;
                    239:        int len;
                    240:        struct authunix_parms *aup;
                    241: {
                    242:        register short entry;
                    243:        struct timeval now;
                    244: 
                    245:        head = previ(head);
                    246:        entry = cacheindex[head];
                    247:        if (cnt == CACHE_SIZE) { /* full cache, delete lru entry */
                    248:                XDR xdrs;
                    249: 
                    250:                xdrs.x_op = XDR_FREE;
                    251:                deletions++;
                    252:                if (cache[entry].cred_base != NULL) {
                    253:                        mem_free(cache[entry].cred_base,
                    254:                            cache[entry].cred_len);
                    255:                        cache[entry].cred_base = NULL;
                    256:                }
                    257:                (void)xdr_authunix_parms(&xdrs, &cache[entry].aup);
                    258:        } else {
                    259:                cnt++;
                    260:        }
                    261:        /* now add current entry, raw cred must be copied */
                    262:        additions++;
                    263:        cache[entry].aup = *aup;
                    264:        cache[entry].cred_len = len;
                    265:        if ((cache[entry].cred_base = (char *)mem_alloc(len)) == NULL) {
                    266:                fprintf(stderr, "cache_new_user: out of memory\n");
                    267:                additions--;
                    268:                return;
                    269:        }
                    270:        bcopy(base, cache[entry].cred_base, (u_int)len);
                    271:        /* finally compute a new, unique short hand value */
                    272:        cache[entry].sh = ++ last_time.tv_sec;
                    273:        /* don't let real time get ahead of last_time */
                    274:        while (TRUE) {
                    275:                (void)gettimeofday(&now, (struct timezone *)0);
                    276:                if (((long int)now.tv_sec - (long int)last_time.tv_sec) > 0)
                    277:                        break;
                    278:                sleep(1);
                    279:        }
                    280: }
                    281: 
                    282: /*
                    283:  * Initialize the shorthand cache.
                    284:  * Must be called before unix auth can be used!
                    285:  */
                    286: static svcauth_unix_init()
                    287: {
                    288:        register short i;
                    289: 
                    290:        inited++;
                    291:        (void)gettimeofday(&last_time, (struct timezone *)0);
                    292:        for (i = 0; i < CACHE_SIZE; ++i) {
                    293:                cacheindex[i] = i;
                    294:        }
                    295: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.