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"
39 /* return a null security object if nothing else can be done */
41 QuickAuth(struct rx_securityClass **astr, afs_int32 *aindex)
43 struct rx_securityClass *tc;
44 tc = rxnull_NewClientSecurityObject();
46 *aindex = RX_SECIDX_NULL;
50 static int _afsconf_GetRxkadKrb5Key(void *arock, int kvno, int enctype, void *outkey,
53 struct afsconf_dir *adir = arock;
54 struct afsconf_typedKey *kobj;
55 struct rx_opaque *keymat;
56 afsconf_keyType tktype;
60 code = afsconf_GetKeyByTypes(adir, afsconf_rxkad_krb5, kvno, enctype, &kobj);
63 afsconf_typedKey_values(kobj, &tktype, &tkvno, &tenctype, &keymat);
64 if (*keylen < keymat->len) {
65 afsconf_typedKey_put(&kobj);
66 return AFSCONF_BADKEY;
68 memcpy(outkey, keymat->val, keymat->len);
69 *keylen = keymat->len;
70 afsconf_typedKey_put(&kobj);
75 /* Return an appropriate security class and index */
77 afsconf_ServerAuth(void *arock,
78 struct rx_securityClass **astr,
81 struct afsconf_dir *adir = (struct afsconf_dir *) arock;
82 struct rx_securityClass *tclass;
85 tclass = (struct rx_securityClass *)
86 rxkad_NewKrb5ServerSecurityObject(0, adir, afsconf_GetKey,
87 _afsconf_GetRxkadKrb5Key, NULL);
90 *aindex = RX_SECIDX_KAD;
100 GenericAuth(struct afsconf_dir *adir,
101 struct rx_securityClass **astr,
103 rxkad_level enclevel)
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 tclass = (struct rx_securityClass *)
174 rxkad_NewClientSecurityObject(enclevel, &session, kvno, ticketLen,
177 *aindex = RX_SECIDX_KAD;
181 /* build a fake ticket for 'afs' using keys from adir, returning an
182 * appropriate security class and index
185 afsconf_ClientAuth(void *arock, struct rx_securityClass ** astr,
188 struct afsconf_dir * adir = (struct afsconf_dir *) arock;
192 rc = GenericAuth(adir, astr, aindex, rxkad_clear);
197 /* build a fake ticket for 'afs' using keys from adir, returning an
198 * appropriate security class and index. This one, unlike the above,
199 * tells rxkad to encrypt the data, too.
202 afsconf_ClientAuthSecure(void *arock,
203 struct rx_securityClass **astr,
206 struct afsconf_dir *adir = (struct afsconf_dir *) arock;
210 rc = GenericAuth(adir, astr, aindex, rxkad_crypt);
216 * Print an rxgk token and make a security class with it
218 * Print an rxgk token and build a security class from it, returning the
219 * correct index along with the class.
221 * As with the other ClientAuth variants, fall back to rxnull on errors.
222 * The caller can check the returned aindex if necessary.
224 * If 'crypt' is nonzero, use the _CRYPT security level. Otherwise, if 'auth'
225 * is nonzero, use the _AUTH security level. Otherwise, use _CLEAR.
228 _ClientAuthRXGK(void *arock, struct rx_securityClass **aclass,
229 afs_int32 *aindex, int crypt, int auth)
232 struct rx_securityClass *tclass;
233 struct rx_opaque token = RX_EMPTY_OPAQUE;
235 RXGK_TokenInfo tokeninfo;
236 rxgk_key cell_key = NULL, k0 = NULL;
237 afs_int32 code, kvno, cell_enctype, k0_enctype;
239 memset(&tokeninfo, 0, sizeof(tokeninfo));
242 level = RXGK_LEVEL_CRYPT;
244 level = RXGK_LEVEL_AUTH;
246 level = RXGK_LEVEL_CLEAR;
248 code = afsconf_GetLatestRXGKKey(arock, &kvno, &cell_enctype, &cell_key);
252 /* assume that cell_key's enctype works for the our token's k0, too */
253 k0_enctype = cell_enctype;
255 tokeninfo.enctype = k0_enctype;
256 tokeninfo.level = level;
257 code = rxgk_print_token_and_key(&token, &tokeninfo, cell_key, kvno,
261 tclass = rxgk_NewClientSecurityObject(level, k0_enctype, k0, &token);
263 code = RXGK_INCONSISTENCY;
265 rxgk_release_key(&cell_key);
266 rxgk_release_key(&k0);
267 rx_opaque_freeContents(&token);
269 return QuickAuth(aclass, aindex);
271 *aindex = RX_SECIDX_GK;
273 #else /* AFS_RXGK_ENV */
274 return QuickAuth(aclass, aindex);
275 #endif /* !AFS_RXGK_ENV */
279 afsconf_ClientAuthRXGKClear(void *arock, struct rx_securityClass **aclass,
282 return _ClientAuthRXGK(arock, aclass, aindex, 0, 0);
286 afsconf_ClientAuthRXGKAuth(void *arock, struct rx_securityClass **aclass,
289 return _ClientAuthRXGK(arock, aclass, aindex, 0, 1);
293 afsconf_ClientAuthRXGKCrypt(void *arock, struct rx_securityClass **aclass,
296 return _ClientAuthRXGK(arock, aclass, aindex, 1, 0);
300 * Build a security class from the user's current tokens
302 * This function constructs an RX security class from a user's current
305 * @param[in] info The cell information structure
306 * @param[in] flags Security flags describing the desired mechanism
307 * @param[out] sc The selected security class
308 * @param[out] scIndex The index of the selected class
309 * @parma[out] expires The expiry time of the tokens used to build the class
311 * Only the AFSCONF_SECOPTS_ALWAYSENCRYPT flag will modify the behaviour of
312 * this function - it determines whether a cleartext, or encrypting, security
316 * 0 on success, non-zero on failure. An error code of
317 * AFSCONF_NO_SECURITY_CLASS indicates that were were unable to build a
318 * security class using the selected tokens.
322 afsconf_ClientAuthToken(struct afsconf_cell *info,
323 afsconf_secflags flags,
324 struct rx_securityClass **sc,
328 struct ktc_setTokenData *tokenSet = NULL;
329 struct ktc_token ttoken;
334 *scIndex = RX_SECIDX_NULL;
336 if ((flags & AFSCONF_SECOPTS_RXGK)) {
337 /* We don't support non-printed rxgk tokens yet */
338 code = AFSCONF_NO_SECURITY_CLASS;
342 code = ktc_GetTokenEx(info->name, &tokenSet);
346 code = token_extractRxkad(tokenSet, &ttoken, NULL, NULL);
348 /* XXX - We should think about how to handle this */
349 if (ttoken.kvno < 0 || ttoken.kvno > 256) {
351 "funny kvno (%d) in ticket, proceeding\n",
354 if (flags & AFSCONF_SECOPTS_ALWAYSENCRYPT)
355 encryptLevel = rxkad_crypt;
357 encryptLevel = rxkad_clear;
358 *sc = rxkad_NewClientSecurityObject(encryptLevel,
363 *scIndex = RX_SECIDX_KAD;
365 *expires = ttoken.endTime;
369 token_FreeSet(&tokenSet);
372 return AFSCONF_NO_SECURITY_CLASS;
378 * Set the security flags to be used for a particular configuration
381 afsconf_SetSecurityFlags(struct afsconf_dir *dir,
382 afsconf_secflags flags)
384 dir->securityFlags = flags;
388 LogDesWarning(struct afsconf_bsso_info *info)
390 if (info->logger == NULL) {
393 /* The blank newlines help this stand out a bit more in the log. */
394 (*info->logger)("\n");
395 (*info->logger)("WARNING: You are using single-DES keys in a KeyFile. Using "
397 (*info->logger)("WARNING: long-term keys is considered insecure, and it is "
399 (*info->logger)("WARNING: recommended that you migrate to stronger "
400 "encryption. See\n");
401 (*info->logger)("WARNING: OPENAFS-SA-2013-003 on "
402 "http://www.openafs.org/security/\n");
403 (*info->logger)("WARNING: for details.\n");
404 (*info->logger)("\n");
408 LogNoKeysWarning(struct afsconf_bsso_info *info)
410 if (info->logger == NULL) {
413 (*info->logger)("WARNING: No encryption keys found! "
414 "All authenticated accesses will fail. "
415 "Run akeyconvert or asetkey to import encryption keys.\n");
418 /* Older version of afsconf_BuildServerSecurityObjects_int. In-tree callers
419 * should use afsconf_BuildServerSecurityObjects_int where possible. */
421 afsconf_BuildServerSecurityObjects(void *rock,
422 struct rx_securityClass ***classes,
423 afs_int32 *numClasses)
425 struct afsconf_bsso_info info;
426 memset(&info, 0, sizeof(info));
428 afsconf_BuildServerSecurityObjects_int(&info, classes, numClasses);
432 * Build a set of security classes suitable for a server accepting
433 * incoming connections
436 afsconf_BuildServerSecurityObjects_int(struct afsconf_bsso_info *info,
437 struct rx_securityClass ***classes,
438 afs_int32 *numClasses)
440 struct afsconf_dir *dir = info->dir;
442 if (afsconf_GetLatestKey(dir, NULL, NULL) == 0) {
445 if (afsconf_CountKeys(dir) == 0) {
446 LogNoKeysWarning(info);
449 *numClasses = RX_SECIDX_GK+1;
451 *classes = calloc(*numClasses, sizeof(**classes));
453 (*classes)[RX_SECIDX_NULL] = rxnull_NewServerSecurityObject();
454 (*classes)[RX_SECIDX_KAD] =
455 rxkad_NewKrb5ServerSecurityObject(0, dir, afsconf_GetKey,
456 _afsconf_GetRxkadKrb5Key, NULL);
458 if (dir->securityFlags & AFSCONF_SECOPTS_ALWAYSENCRYPT)
459 (*classes)[RX_SECIDX_KAE] =
460 rxkad_NewKrb5ServerSecurityObject(rxkad_crypt, dir, afsconf_GetKey,
461 _afsconf_GetRxkadKrb5Key, NULL);
463 (*classes)[RX_SECIDX_GK] =
464 rxgk_NewServerSecurityObject(rock, afsconf_GetRXGKKey);
469 * Pick a security class to use for an outgoing connection
471 * This function selects an RX security class to use for an outgoing
472 * connection, based on the set of security flags provided.
475 * The configuration directory structure for this cell. If NULL,
476 * no classes requiring local configuration will be returned.
478 * A set of flags to determine the properties of the security class which
480 * - AFSCONF_SECOPTS_NOAUTH - return an anonymous secirty class
481 * - AFSCONF_SECOPTS_LOCALAUTH - use classes which have local key
482 * material available.
483 * - AFSCONF_SECOPTS_ALWAYSENCRYPT - use classes in encrypting, rather
484 * than authentication or integrity modes.
485 * - AFSCONF_SECOPTS_FALLBACK_NULL - if no suitable class can be found,
486 * then fallback to the rxnull security class.
487 * - AFSCONF_SECOPTS_NEVERENCRYPT - avoid encrypting classes (currently
488 * only valid with _RXGK)
489 * - AFSCONF_SECOPTS_ALWAYSCLEAR - avoid encrypting or authenticating
490 * classes (always use "clear" security classes) (currently
491 * only valid with _RXGK)
492 * - AFSCONF_SECOPTS_RXGK - only use rxgk security classes (currently
493 * only valid with _LOCALAUTH)
495 * The cell information structure for the current cell. If this is NULL,
496 * then use a version locally obtained using the cellName.
497 * @param[in] cellName
498 * The cellName to use when obtaining cell information (may be NULL if
501 * The selected security class
502 * @param[out] scIndex
503 * The index of the selected security class
504 * @param[out] expires
505 * The expiry time of the tokens used to construct the class. Will be
506 * NEVER_DATE if the class has an unlimited lifetime. If NULL, the
507 * function won't store the expiry date.
510 * Returns 0 on success, or a com_err error code on failure.
513 afsconf_PickClientSecObj(struct afsconf_dir *dir, afsconf_secflags flags,
514 struct afsconf_cell *info,
515 char *cellName, struct rx_securityClass **sc,
516 afs_int32 *scIndex, time_t *expires) {
517 struct afsconf_cell localInfo;
521 *scIndex = RX_SECIDX_NULL;
525 if ( !(flags & AFSCONF_SECOPTS_NOAUTH) ) {
527 return AFSCONF_NOCELLDB;
529 if (flags & AFSCONF_SECOPTS_LOCALAUTH) {
530 if ((flags & AFSCONF_SECOPTS_RXGK)) {
531 if ((flags & AFSCONF_SECOPTS_ALWAYSCLEAR))
532 code = afsconf_ClientAuthRXGKClear(dir, sc, scIndex);
533 else if ((flags & AFSCONF_SECOPTS_NEVERENCRYPT))
534 code = afsconf_ClientAuthRXGKAuth(dir, sc, scIndex);
536 code = afsconf_ClientAuthRXGKCrypt(dir, sc, scIndex);
538 } else if (flags & AFSCONF_SECOPTS_ALWAYSENCRYPT)
539 code = afsconf_ClientAuthSecure(dir, sc, scIndex);
541 code = afsconf_ClientAuth(dir, sc, scIndex);
546 /* The afsconf_ClientAuth functions will fall back to giving
547 * a rxnull object, which we don't want if localauth has been
548 * explicitly requested. Check for this, and bail out if we
549 * get one. Note that this leaks a security object at present
551 if (!(flags & AFSCONF_SECOPTS_FALLBACK_NULL) &&
552 *scIndex == RX_SECIDX_NULL) {
554 code = AFSCONF_NOTFOUND;
559 *expires = NEVERDATE;
562 code = afsconf_GetCellInfo(dir, cellName, NULL, &localInfo);
568 code = afsconf_ClientAuthToken(info, flags, sc, scIndex, expires);
569 if (code && !(flags & AFSCONF_SECOPTS_FALLBACK_NULL))
572 /* If we didn't get a token, we'll just run anonymously */
577 *sc = rxnull_NewClientSecurityObject();
578 *scIndex = RX_SECIDX_NULL;
580 *expires = NEVERDATE;