OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [librpc/] [src/] [rpc/] [auth_des.c] - Blame information for rev 735

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 30 unneback
/*
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
/*
30
 * Copyright (c) 1988 by Sun Microsystems, Inc.
31
 */
32
/*
33
 * auth_des.c, client-side implementation of DES authentication
34
 */
35
#include <string.h>
36
#include <stdlib.h>
37
#include <unistd.h>
38
#include <sys/cdefs.h>
39
#include <rpc/des_crypt.h>
40
#include <rpc/types.h>
41
#include <rpc/xdr.h>
42
#include <rpc/auth.h>
43
#include <rpc/auth_des.h>
44
#include <netinet/in.h> /* XXX: just to get htonl() and ntohl() */
45
#include <sys/socket.h>
46
#undef NIS
47
#include <rpcsvc/nis.h>
48
 
49
#if defined(LIBC_SCCS) && !defined(lint)
50
/* from: static char sccsid[] =         "@(#)auth_des.c 2.2 88/07/29 4.0 RPCSRC; from 1.9 88/02/08 SMI"; */
51
static const char rcsid[] = "$FreeBSD: src/lib/libc/rpc/auth_des.c,v 1.3 1999/08/28 00:00:32 peter Exp $";
52
#endif
53
 
54
extern bool_t __rpc_get_time_offset __P(( struct timeval *, nis_server *,
55
                                                char *, char **, struct sockaddr_in * ));
56
extern int rtime __P(( struct sockaddr_in *, struct timeval *, struct timeval *));
57
extern bool_t xdr_authdes_cred __P(( XDR *, struct authdes_cred * ));
58
extern bool_t xdr_authdes_verf __P(( XDR *, struct authdes_verf * ));
59
 
60
#define MILLION         1000000L
61
#define RTIME_TIMEOUT 5         /* seconds to wait for sync */
62
 
63
#define AUTH_PRIVATE(auth)      (struct ad_private *) auth->ah_private
64
#define ALLOC(object_type)      (object_type *) mem_alloc(sizeof(object_type))
65
#define FREE(ptr, size)         mem_free((char *)(ptr), (int) size)
66
#define ATTEMPT(xdr_op)         if (!(xdr_op)) return (FALSE)
67
 
68
#define debug(msg)               /*printf("%s\n", msg) */
69
 
70
/*
71
 * DES authenticator operations vector
72
 */
73
static void     authdes_nextverf();
74
static bool_t   authdes_marshal();
75
static bool_t   authdes_validate();
76
static bool_t   authdes_refresh();
77
static void     authdes_destroy();
78
static struct auth_ops authdes_ops = {
79
        authdes_nextverf,
80
        authdes_marshal,
81
        authdes_validate,
82
        authdes_refresh,
83
        authdes_destroy
84
};
85
#ifdef foo
86
static bool_t   synchronize __P(( struct sockaddr *, struct timeval *));
87
#endif
88
/*
89
 * This struct is pointed to by the ah_private field of an "AUTH *"
90
 */
91
struct ad_private {
92
        char *ad_fullname;              /* client's full name */
93
        u_int ad_fullnamelen;           /* length of name, rounded up */
94
        char *ad_servername;            /* server's full name */
95
        u_int ad_servernamelen;         /* length of name, rounded up */
96
        u_int ad_window;                /* client specified window */
97
        bool_t ad_dosync;               /* synchronize? */
98
        struct sockaddr ad_syncaddr;    /* remote host to synch with */
99
        char *ad_timehost;              /* remote host to synch with */
100
        struct timeval ad_timediff;     /* server's time - client's time */
101
        u_long ad_nickname;             /* server's nickname for client */
102
        struct authdes_cred ad_cred;    /* storage for credential */
103
        struct authdes_verf ad_verf;    /* storage for verifier */
104
        struct timeval ad_timestamp;    /* timestamp sent */
105
        des_block ad_xkey;              /* encrypted conversation key */
106
        u_char ad_pkey[1024];           /* Server's actual public key */
107
        char *ad_netid;                 /* Timehost netid */
108
        char *ad_uaddr;                 /* Timehost uaddr */
109
        nis_server *ad_nis_srvr;        /* NIS+ server struct */
110
};
111
 
112
 
113
/*
114
 * Create the client des authentication object
115
 */
116
AUTH *
117
authdes_create(servername, window, syncaddr, ckey)
118
        char *servername;               /* network name of server */
119
        u_int window;                   /* time to live */
120
        struct sockaddr *syncaddr;      /* optional addr of host to sync with */
121
        des_block *ckey;                /* optional conversation key to use*/
122
{
123
 
124
        AUTH *auth;
125
        struct ad_private *ad;
126
        char namebuf[MAXNETNAMELEN+1];
127
        u_char  pkey_data[1024];
128
 
129
        if (!getpublickey(servername, pkey_data))
130
                return(NULL);
131
 
132
        /*
133
         * Allocate everything now
134
         */
135
        auth = ALLOC(AUTH);
136
        ad = ALLOC(struct ad_private);
137
        (void) getnetname(namebuf);
138
 
139
        ad->ad_fullnamelen = RNDUP(strlen(namebuf));
140
        ad->ad_fullname = (char *)mem_alloc(ad->ad_fullnamelen + 1);
141
 
142
        ad->ad_servernamelen = strlen(servername);
143
        ad->ad_servername = (char *)mem_alloc(ad->ad_servernamelen + 1);
144
 
145
        if (auth == NULL || ad == NULL || ad->ad_fullname == NULL ||
146
            ad->ad_servername == NULL) {
147
                debug("authdes_create: out of memory");
148
                goto failed;
149
        }
150
 
151
        /*
152
         * Set up private data
153
         */
154
        bcopy(namebuf, ad->ad_fullname, ad->ad_fullnamelen + 1);
155
        bcopy(servername, ad->ad_servername, ad->ad_servernamelen + 1);
156
        bcopy(pkey_data, ad->ad_pkey, strlen(pkey_data) + 1);
157
        if (syncaddr != NULL) {
158
                ad->ad_syncaddr = *syncaddr;
159
                ad->ad_dosync = TRUE;
160
        } else {
161
                ad->ad_dosync = FALSE;
162
        }
163
        ad->ad_window = window;
164
        if (ckey == NULL) {
165
                if (key_gendes(&auth->ah_key) < 0) {
166
                        debug("authdes_create: unable to gen conversation key");
167
                        return (NULL);
168
                }
169
        } else {
170
                auth->ah_key = *ckey;
171
        }
172
 
173
        /*
174
         * Set up auth handle
175
         */
176
        auth->ah_cred.oa_flavor = AUTH_DES;
177
        auth->ah_verf.oa_flavor = AUTH_DES;
178
        auth->ah_ops = &authdes_ops;
179
        auth->ah_private = (caddr_t)ad;
180
 
181
        if (!authdes_refresh(auth)) {
182
                goto failed;
183
        }
184
        return (auth);
185
 
186
failed:
187
        if (auth != NULL)
188
                FREE(auth, sizeof(AUTH));
189
        if (ad != NULL)
190
                FREE(ad, sizeof(struct ad_private));
191
        if (ad->ad_fullname != NULL)
192
                FREE(ad->ad_fullname, ad->ad_fullnamelen + 1);
193
        if (ad->ad_servername != NULL)
194
                FREE(ad->ad_servername, ad->ad_servernamelen + 1);
195
        return (NULL);
196
}
197
 
198
/*
199
 * Slightly modified version of authdes_create which takes the public key
200
 * of the server principal as an argument. This spares us a call to
201
 * getpublickey() which in the nameserver context can cause a deadlock.
202
 */
203
AUTH *
204
authdes_pk_create(servername, pkey, window, timehost, ckey, srvr)
205
        char *servername;               /* network name of server */
206
        netobj *pkey;                   /* public key of server */
207
        u_int window;                   /* time to live */
208
        char *timehost;                 /* optional hostname to sync with */
209
        des_block *ckey;                /* optional conversation key to use */
210
        nis_server *srvr;               /* optional NIS+ server struct */
211
{
212
        AUTH *auth;
213
        struct ad_private *ad;
214
        char namebuf[MAXNETNAMELEN+1];
215
 
216
        /*
217
         * Allocate everything now
218
         */
219
        auth = ALLOC(AUTH);
220
        if (auth == NULL) {
221
                debug("authdes_pk_create: out of memory");
222
                return (NULL);
223
        }
224
        ad = ALLOC(struct ad_private);
225
        if (ad == NULL) {
226
                debug("authdes_pk_create: out of memory");
227
                goto failed;
228
        }
229
        ad->ad_fullname = ad->ad_servername = NULL; /* Sanity reasons */
230
        ad->ad_timehost = NULL;
231
        ad->ad_netid = NULL;
232
        ad->ad_uaddr = NULL;
233
        ad->ad_nis_srvr = NULL;
234
        ad->ad_timediff.tv_sec = 0;
235
        ad->ad_timediff.tv_usec = 0;
236
        memcpy(ad->ad_pkey, pkey->n_bytes, pkey->n_len);
237
        if (!getnetname(namebuf))
238
                goto failed;
239
        ad->ad_fullnamelen = RNDUP((u_int) strlen(namebuf));
240
        ad->ad_fullname = (char *)mem_alloc(ad->ad_fullnamelen + 1);
241
        ad->ad_servernamelen = strlen(servername);
242
        ad->ad_servername = (char *)mem_alloc(ad->ad_servernamelen + 1);
243
 
244
        if (ad->ad_fullname == NULL || ad->ad_servername == NULL) {
245
                debug("authdes_pk_create: out of memory");
246
                goto failed;
247
        }
248
        if (timehost != NULL) {
249
                ad->ad_timehost = (char *)mem_alloc(strlen(timehost) + 1);
250
                if (ad->ad_timehost == NULL) {
251
                        debug("authdes_pk_create: out of memory");
252
                        goto failed;
253
                }
254
                memcpy(ad->ad_timehost, timehost, strlen(timehost) + 1);
255
                ad->ad_dosync = TRUE;
256
        } else if (srvr != NULL) {
257
                ad->ad_nis_srvr = srvr; /* transient */
258
                ad->ad_dosync = TRUE;
259
        } else {
260
                ad->ad_dosync = FALSE;
261
        }
262
        memcpy(ad->ad_fullname, namebuf, ad->ad_fullnamelen + 1);
263
        memcpy(ad->ad_servername, servername, ad->ad_servernamelen + 1);
264
        ad->ad_window = window;
265
        if (ckey == NULL) {
266
                if (key_gendes(&auth->ah_key) < 0) {
267
                        debug("authdes_pk_create: unable to gen conversation key");
268
                        goto failed;
269
                }
270
        } else {
271
                auth->ah_key = *ckey;
272
        }
273
 
274
        /*
275
         * Set up auth handle
276
         */
277
        auth->ah_cred.oa_flavor = AUTH_DES;
278
        auth->ah_verf.oa_flavor = AUTH_DES;
279
        auth->ah_ops = &authdes_ops;
280
        auth->ah_private = (caddr_t)ad;
281
 
282
        if (!authdes_refresh(auth)) {
283
                goto failed;
284
        }
285
        ad->ad_nis_srvr = NULL; /* not needed any longer */
286
        return (auth);
287
 
288
failed:
289
        if (auth)
290
                FREE(auth, sizeof (AUTH));
291
        if (ad) {
292
                if (ad->ad_fullname)
293
                        FREE(ad->ad_fullname, ad->ad_fullnamelen + 1);
294
                if (ad->ad_servername)
295
                        FREE(ad->ad_servername, ad->ad_servernamelen + 1);
296
                if (ad->ad_timehost)
297
                        FREE(ad->ad_timehost, strlen(ad->ad_timehost) + 1);
298
                if (ad->ad_netid)
299
                        free(ad->ad_netid);
300
                if (ad->ad_uaddr)
301
                        free(ad->ad_uaddr);
302
                FREE(ad, sizeof (struct ad_private));
303
        }
304
        return (NULL);
305
}
306
/*
307
 * Implement the five authentication operations
308
 */
309
 
310
 
311
/*
312
 * 1. Next Verifier
313
 */
314
/*ARGSUSED*/
315
static void
316
authdes_nextverf(auth)
317
        AUTH *auth;
318
{
319
        /* what the heck am I supposed to do??? */
320
}
321
 
322
 
323
 
324
/*
325
 * 2. Marshal
326
 */
327
static bool_t
328
authdes_marshal(auth, xdrs)
329
        AUTH *auth;
330
        XDR *xdrs;
331
{
332
        struct ad_private *ad = AUTH_PRIVATE(auth);
333
        struct authdes_cred *cred = &ad->ad_cred;
334
        struct authdes_verf *verf = &ad->ad_verf;
335
        des_block cryptbuf[2];
336
        des_block ivec;
337
        int status;
338
        long len;
339
        int32_t *ixdr;
340
 
341
        /*
342
         * Figure out the "time", accounting for any time difference
343
         * with the server if necessary.
344
         */
345
        (void) gettimeofday(&ad->ad_timestamp, (struct timezone *)NULL);
346
        ad->ad_timestamp.tv_sec += ad->ad_timediff.tv_sec;
347
        ad->ad_timestamp.tv_usec += ad->ad_timediff.tv_usec;
348
        if (ad->ad_timestamp.tv_usec >= MILLION) {
349
                ad->ad_timestamp.tv_usec -= MILLION;
350
                ad->ad_timestamp.tv_sec += 1;
351
        }
352
 
353
        /*
354
         * XDR the timestamp and possibly some other things, then
355
         * encrypt them.
356
         */
357
        ixdr = (int32_t *)cryptbuf;
358
        IXDR_PUT_LONG(ixdr, ad->ad_timestamp.tv_sec);
359
        IXDR_PUT_LONG(ixdr, ad->ad_timestamp.tv_usec);
360
        if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
361
                IXDR_PUT_U_LONG(ixdr, ad->ad_window);
362
                IXDR_PUT_U_LONG(ixdr, ad->ad_window - 1);
363
                ivec.key.high = ivec.key.low = 0;
364
                status = cbc_crypt((char *)&auth->ah_key, (char *)cryptbuf,
365
                        2*sizeof(des_block), DES_ENCRYPT | DES_HW, (char *)&ivec);
366
        } else {
367
                status = ecb_crypt((char *)&auth->ah_key, (char *)cryptbuf,
368
                        sizeof(des_block), DES_ENCRYPT | DES_HW);
369
        }
370
        if (DES_FAILED(status)) {
371
                debug("authdes_marshal: DES encryption failure");
372
                return (FALSE);
373
        }
374
        ad->ad_verf.adv_xtimestamp = cryptbuf[0];
375
        if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
376
                ad->ad_cred.adc_fullname.window = cryptbuf[1].key.high;
377
                ad->ad_verf.adv_winverf = cryptbuf[1].key.low;
378
        } else {
379
                ad->ad_cred.adc_nickname = ad->ad_nickname;
380
                ad->ad_verf.adv_winverf = 0;
381
        }
382
 
383
        /*
384
         * Serialize the credential and verifier into opaque
385
         * authentication data.
386
         */
387
        if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
388
                len = ((1 + 1 + 2 + 1)*BYTES_PER_XDR_UNIT + ad->ad_fullnamelen);
389
        } else {
390
                len = (1 + 1)*BYTES_PER_XDR_UNIT;
391
        }
392
 
393
        if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) {
394
                IXDR_PUT_LONG(ixdr, AUTH_DES);
395
                IXDR_PUT_LONG(ixdr, len);
396
        } else {
397
                ATTEMPT(xdr_putlong(xdrs, (long *)&auth->ah_cred.oa_flavor));
398
                ATTEMPT(xdr_putlong(xdrs, &len));
399
        }
400
        ATTEMPT(xdr_authdes_cred(xdrs, cred));
401
 
402
        len = (2 + 1)*BYTES_PER_XDR_UNIT;
403
        if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) {
404
                IXDR_PUT_LONG(ixdr, AUTH_DES);
405
                IXDR_PUT_LONG(ixdr, len);
406
        } else {
407
                ATTEMPT(xdr_putlong(xdrs, (long *)&auth->ah_verf.oa_flavor));
408
                ATTEMPT(xdr_putlong(xdrs, &len));
409
        }
410
        ATTEMPT(xdr_authdes_verf(xdrs, verf));
411
        return (TRUE);
412
}
413
 
414
 
415
/*
416
 * 3. Validate
417
 */
418
static bool_t
419
authdes_validate(auth, rverf)
420
        AUTH *auth;
421
        struct opaque_auth *rverf;
422
{
423
        struct ad_private *ad = AUTH_PRIVATE(auth);
424
        struct authdes_verf verf;
425
        int status;
426
        register u_long *ixdr;
427
 
428
        if (rverf->oa_length != (2 + 1) * BYTES_PER_XDR_UNIT) {
429
                return (FALSE);
430
        }
431
        ixdr = (u_long *)rverf->oa_base;
432
        verf.adv_xtimestamp.key.high = (u_long)*ixdr++;
433
        verf.adv_xtimestamp.key.low = (u_long)*ixdr++;
434
        verf.adv_int_u = (u_long)*ixdr++;       /* nickname not XDR'd ! */
435
 
436
        /*
437
         * Decrypt the timestamp
438
         */
439
        status = ecb_crypt((char *)&auth->ah_key, (char *)&verf.adv_xtimestamp,
440
                sizeof(des_block), DES_DECRYPT | DES_HW);
441
 
442
        if (DES_FAILED(status)) {
443
                debug("authdes_validate: DES decryption failure");
444
                return (FALSE);
445
        }
446
 
447
        /*
448
         * xdr the decrypted timestamp
449
         */
450
        ixdr = (u_long *)verf.adv_xtimestamp.c;
451
        verf.adv_timestamp.tv_sec = IXDR_GET_LONG(ixdr) + 1;
452
        verf.adv_timestamp.tv_usec = IXDR_GET_LONG(ixdr);
453
 
454
        /*
455
         * validate
456
         */
457
        if (bcmp((char *)&ad->ad_timestamp, (char *)&verf.adv_timestamp,
458
                 sizeof(struct timeval)) != 0) {
459
                debug("authdes_validate: verifier mismatch\n");
460
                return (FALSE);
461
        }
462
 
463
        /*
464
         * We have a nickname now, let's use it
465
         */
466
        ad->ad_nickname = verf.adv_nickname;
467
        ad->ad_cred.adc_namekind = ADN_NICKNAME;
468
        return (TRUE);
469
}
470
 
471
/*
472
 * 4. Refresh
473
 */
474
static bool_t
475
authdes_refresh(auth)
476
        AUTH *auth;
477
{
478
        struct ad_private *ad = AUTH_PRIVATE(auth);
479
        struct authdes_cred *cred = &ad->ad_cred;
480
        netobj          pkey;
481
 
482
        if (ad->ad_dosync &&
483
#ifdef old
484
                        !synchronize(&ad->ad_syncaddr, &ad->ad_timediff)) {
485
#else
486
                        !__rpc_get_time_offset(&ad->ad_timediff,ad->ad_nis_srvr,
487
                                               ad->ad_timehost, &(ad->ad_uaddr),
488
                                (struct sockaddr_in *)&(ad->ad_syncaddr))) {
489
#endif
490
                /*
491
                 * Hope the clocks are synced!
492
                 */
493
                ad->ad_timediff.tv_sec = ad->ad_timediff.tv_usec = 0;
494
                ad->ad_dosync = 0;
495
                debug("authdes_refresh: unable to synchronize with server");
496
        }
497
        ad->ad_xkey = auth->ah_key;
498
        pkey.n_bytes = (char *)(ad->ad_pkey);
499
        pkey.n_len = strlen((char *)ad->ad_pkey) + 1;
500
        if (key_encryptsession_pk(ad->ad_servername, &pkey, &ad->ad_xkey) < 0) {
501
                debug("authdes_create: unable to encrypt conversation key");
502
                return (FALSE);
503
        }
504
        cred->adc_fullname.key = ad->ad_xkey;
505
        cred->adc_namekind = ADN_FULLNAME;
506
        cred->adc_fullname.name = ad->ad_fullname;
507
        return (TRUE);
508
}
509
 
510
 
511
/*
512
 * 5. Destroy
513
 */
514
static void
515
authdes_destroy(auth)
516
        AUTH *auth;
517
{
518
        struct ad_private *ad = AUTH_PRIVATE(auth);
519
 
520
        FREE(ad->ad_fullname, ad->ad_fullnamelen + 1);
521
        FREE(ad->ad_servername, ad->ad_servernamelen + 1);
522
        FREE(ad, sizeof(struct ad_private));
523
        FREE(auth, sizeof(AUTH));
524
}
525
 
526
 
527
#ifdef old
528
/*
529
 * Synchronize with the server at the given address, that is,
530
 * adjust timep to reflect the delta between our clocks
531
 */
532
static bool_t
533
synchronize(syncaddr, timep)
534
        struct sockaddr *syncaddr;
535
        struct timeval *timep;
536
{
537
        struct timeval mytime;
538
        struct timeval timeout;
539
 
540
        timeout.tv_sec = RTIME_TIMEOUT;
541
        timeout.tv_usec = 0;
542
        if (rtime((struct sockaddr_in *)syncaddr, timep, NULL /*&timeout*/) < 0) {
543
                return (FALSE);
544
        }
545
        (void) gettimeofday(&mytime, (struct timezone *)NULL);
546
        timep->tv_sec -= mytime.tv_sec;
547
        if (mytime.tv_usec > timep->tv_usec) {
548
                timep->tv_sec -= 1;
549
                timep->tv_usec += MILLION;
550
        }
551
        timep->tv_usec -= mytime.tv_usec;
552
        return (TRUE);
553
}
554
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.