2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
16 #ifdef IGNORE_SOME_GCC_WARNINGS
17 # pragma GCC diagnostic warning "-Wdeprecated-declarations"
21 #include <hcrypto/des.h>
22 #include <hcrypto/rand.h>
27 #include <afs/pthread_glock.h>
29 #include "cellconfig.h"
34 /* return a null security object if nothing else can be done */
36 QuickAuth(struct rx_securityClass **astr, afs_int32 *aindex)
38 struct rx_securityClass *tc;
39 tc = rxnull_NewClientSecurityObject();
41 *aindex = RX_SECIDX_NULL;
46 static int _afsconf_GetRxkadKrb5Key(void *arock, int kvno, int enctype, void *outkey,
49 struct afsconf_dir *adir = arock;
50 struct afsconf_typedKey *kobj;
51 struct rx_opaque *keymat;
52 afsconf_keyType tktype;
56 code = afsconf_GetKeyByTypes(adir, afsconf_rxkad_krb5, kvno, enctype, &kobj);
59 afsconf_typedKey_values(kobj, &tktype, &tkvno, &tenctype, &keymat);
60 if (*keylen < keymat->len) {
61 afsconf_typedKey_put(&kobj);
62 return AFSCONF_BADKEY;
64 memcpy(outkey, keymat->val, keymat->len);
65 *keylen = keymat->len;
66 afsconf_typedKey_put(&kobj);
71 /* Return an appropriate security class and index */
73 afsconf_ServerAuth(void *arock,
74 struct rx_securityClass **astr,
77 struct afsconf_dir *adir = (struct afsconf_dir *) arock;
78 struct rx_securityClass *tclass;
81 tclass = (struct rx_securityClass *)
82 rxkad_NewKrb5ServerSecurityObject(0, adir, afsconf_GetKey,
83 _afsconf_GetRxkadKrb5Key, NULL);
86 *aindex = RX_SECIDX_KAD;
94 #endif /* !defined(UKERNEL) */
97 GenericAuth(struct afsconf_dir *adir,
98 struct rx_securityClass **astr,
100 rxkad_level enclevel)
103 return QuickAuth(astr, aindex);
105 int enctype_preflist[]={18, 17, 23, 16, 0};
107 struct ktc_encryptionKey key, session;
108 struct rx_securityClass *tclass;
113 struct afsconf_typedKey *kobj;
114 struct rx_opaque *keymat;
117 /* first, find the right key and kvno to use */
119 et = enctype_preflist;
121 code = afsconf_GetLatestKeyByTypes(adir, afsconf_rxkad_krb5, *et,
124 afsconf_keyType tktype;
126 afsconf_typedKey_values(kobj, &tktype, &kvno, &tenctype, &keymat);
127 RAND_add(keymat->val, keymat->len, 0.0);
135 code = afsconf_GetLatestKey(adir, &kvno, &key);
137 return QuickAuth(astr, aindex);
139 /* next create random session key, using key for seed to good random */
140 DES_init_random_number_generator((DES_cblock *) &key);
142 code = DES_new_random_key((DES_cblock *) &session);
145 afsconf_typedKey_put(&kobj);
146 return QuickAuth(astr, aindex);
150 ticketLen = sizeof(tbuffer);
151 memset(tbuffer, '\0', sizeof(tbuffer));
153 tkt_MakeTicket5(tbuffer, &ticketLen, *et, &kvno, keymat->val,
154 keymat->len, AUTH_SUPERUSER, "", "", 0, 0x7fffffff,
155 &session, "afs", "");
156 afsconf_typedKey_put(&kobj);
158 /* now create the actual ticket */
159 ticketLen = sizeof(tbuffer);
160 memset(tbuffer, '\0', sizeof(tbuffer));
162 tkt_MakeTicket(tbuffer, &ticketLen, &key, AUTH_SUPERUSER, "", "", 0,
163 0xffffffff, &session, 0, "afs", "");
164 /* parms were buffer, ticketlen, key to seal ticket with, principal
165 * name, instance and cell, start time, end time, session key to seal
166 * in ticket, inet host, server name and server instance */
169 return QuickAuth(astr, aindex);
172 /* Next, we have ticket, kvno and session key, authenticate the connection.
173 * We use a magic # instead of a constant because of basic compilation
174 * order when compiling the system from scratch (rx/rxkad.h isn't installed
176 tclass = (struct rx_securityClass *)
177 rxkad_NewClientSecurityObject(enclevel, &session, kvno, ticketLen,
180 *aindex = RX_SECIDX_KAD;
185 /* build a fake ticket for 'afs' using keys from adir, returning an
186 * appropriate security class and index
189 afsconf_ClientAuth(void *arock, struct rx_securityClass ** astr,
192 struct afsconf_dir * adir = (struct afsconf_dir *) arock;
196 rc = GenericAuth(adir, astr, aindex, rxkad_clear);
201 /* build a fake ticket for 'afs' using keys from adir, returning an
202 * appropriate security class and index. This one, unlike the above,
203 * tells rxkad to encrypt the data, too.
206 afsconf_ClientAuthSecure(void *arock,
207 struct rx_securityClass **astr,
210 struct afsconf_dir *adir = (struct afsconf_dir *) arock;
214 rc = GenericAuth(adir, astr, aindex, rxkad_crypt);
220 * Build a security class from the user's current tokens
222 * This function constructs an RX security class from a user's current
225 * @param[in] info The cell information structure
226 * @param[in] flags Security flags describing the desired mechanism
227 * @param[out] sc The selected security class
228 * @param[out] scIndex The index of the selected class
229 * @parma[out] expires The expiry time of the tokens used to build the class
231 * Only the AFSCONF_SECOPTS_ALWAYSENCRYPT flag will modify the behaviour of
232 * this function - it determines whether a cleartext, or encrypting, security
236 * 0 on success, non-zero on failure. An error code of
237 * AFSCONF_NO_SECURITY_CLASS indicates that were were unable to build a
238 * security class using the selected tokens.
242 afsconf_ClientAuthToken(struct afsconf_cell *info,
243 afsconf_secflags flags,
244 struct rx_securityClass **sc,
248 struct ktc_setTokenData *tokenSet = NULL;
249 struct ktc_token ttoken;
254 *scIndex = RX_SECIDX_NULL;
256 code = ktc_GetTokenEx(info->name, &tokenSet);
260 code = token_extractRxkad(tokenSet, &ttoken, NULL, NULL);
262 /* XXX - We should think about how to handle this */
263 if (ttoken.kvno < 0 || ttoken.kvno > 256) {
265 "funny kvno (%d) in ticket, proceeding\n",
268 if (flags & AFSCONF_SECOPTS_ALWAYSENCRYPT)
269 encryptLevel = rxkad_crypt;
271 encryptLevel = rxkad_clear;
272 *sc = rxkad_NewClientSecurityObject(encryptLevel,
277 *scIndex = RX_SECIDX_KAD;
279 *expires = ttoken.endTime;
283 token_FreeSet(&tokenSet);
286 return AFSCONF_NO_SECURITY_CLASS;
292 * Set the security flags to be used for a particular configuration
295 afsconf_SetSecurityFlags(struct afsconf_dir *dir,
296 afsconf_secflags flags)
298 dir->securityFlags = flags;
302 * Build a set of security classes suitable for a server accepting
303 * incoming connections
305 #if !defined(UKERNEL)
307 afsconf_BuildServerSecurityObjects(void *rock,
308 struct rx_securityClass ***classes,
309 afs_int32 *numClasses)
311 struct afsconf_dir *dir = rock;
313 if (dir->securityFlags & AFSCONF_SECOPTS_ALWAYSENCRYPT)
318 *classes = calloc(*numClasses, sizeof(**classes));
320 (*classes)[0] = rxnull_NewServerSecurityObject();
321 (*classes)[1] = NULL;
322 (*classes)[2] = rxkad_NewKrb5ServerSecurityObject(0, dir,
324 _afsconf_GetRxkadKrb5Key,
327 if (dir->securityFlags & AFSCONF_SECOPTS_ALWAYSENCRYPT)
328 (*classes)[3] = rxkad_NewKrb5ServerSecurityObject(rxkad_crypt, dir,
330 _afsconf_GetRxkadKrb5Key,
336 * Pick a security class to use for an outgoing connection
338 * This function selects an RX security class to use for an outgoing
339 * connection, based on the set of security flags provided.
342 * The configuration directory structure for this cell. If NULL,
343 * no classes requiring local configuration will be returned.
345 * A set of flags to determine the properties of the security class which
347 * - AFSCONF_SECOPTS_NOAUTH - return an anonymous secirty class
348 * - AFSCONF_SECOPTS_LOCALAUTH - use classes which have local key
349 * material available.
350 * - AFSCONF_SECOPTS_ALWAYSENCRYPT - use classes in encrypting, rather
351 * than authentication or integrity modes.
352 * - AFSCONF_SECOPTS_FALLBACK_NULL - if no suitable class can be found,
353 * then fallback to the rxnull security class.
355 * The cell information structure for the current cell. If this is NULL,
356 * then use a version locally obtained using the cellName.
357 * @param[in] cellName
358 * The cellName to use when obtaining cell information (may be NULL if
361 * The selected security class
362 * @param[out] scIndex
363 * The index of the selected security class
364 * @param[out] expires
365 * The expiry time of the tokens used to construct the class. Will be
366 * NEVER_DATE if the class has an unlimited lifetime. If NULL, the
367 * function won't store the expiry date.
370 * Returns 0 on success, or a com_err error code on failure.
373 afsconf_PickClientSecObj(struct afsconf_dir *dir, afsconf_secflags flags,
374 struct afsconf_cell *info,
375 char *cellName, struct rx_securityClass **sc,
376 afs_int32 *scIndex, time_t *expires) {
377 struct afsconf_cell localInfo;
381 *scIndex = RX_SECIDX_NULL;
385 if ( !(flags & AFSCONF_SECOPTS_NOAUTH) ) {
387 return AFSCONF_NOCELLDB;
389 if (flags & AFSCONF_SECOPTS_LOCALAUTH) {
390 if (flags & AFSCONF_SECOPTS_ALWAYSENCRYPT)
391 code = afsconf_ClientAuthSecure(dir, sc, scIndex);
393 code = afsconf_ClientAuth(dir, sc, scIndex);
398 /* The afsconf_ClientAuth functions will fall back to giving
399 * a rxnull object, which we don't want if localauth has been
400 * explicitly requested. Check for this, and bail out if we
401 * get one. Note that this leaks a security object at present
403 if (!(flags & AFSCONF_SECOPTS_FALLBACK_NULL) &&
404 *scIndex == RX_SECIDX_NULL) {
406 code = AFSCONF_NOTFOUND;
411 *expires = NEVERDATE;
414 code = afsconf_GetCellInfo(dir, cellName, NULL, &localInfo);
420 code = afsconf_ClientAuthToken(info, flags, sc, scIndex, expires);
421 if (code && !(flags & AFSCONF_SECOPTS_FALLBACK_NULL))
424 /* If we didn't get a token, we'll just run anonymously */
429 *sc = rxnull_NewClientSecurityObject();
430 *scIndex = RX_SECIDX_NULL;
432 *expires = NEVERDATE;