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>
26 #include <afs/pthread_glock.h>
28 #include "cellconfig.h"
33 /* return a null security object if nothing else can be done */
35 QuickAuth(struct rx_securityClass **astr, afs_int32 *aindex)
37 struct rx_securityClass *tc;
38 tc = rxnull_NewClientSecurityObject();
40 *aindex = RX_SECIDX_NULL;
45 /* Return an appropriate security class and index */
47 afsconf_ServerAuth(void *arock,
48 struct rx_securityClass **astr,
51 struct afsconf_dir *adir = (struct afsconf_dir *) arock;
52 struct rx_securityClass *tclass;
55 tclass = (struct rx_securityClass *)
56 rxkad_NewServerSecurityObject(0, adir, afsconf_GetKey, NULL);
59 *aindex = RX_SECIDX_KAD;
67 #endif /* !defined(UKERNEL) */
70 GenericAuth(struct afsconf_dir *adir,
71 struct rx_securityClass **astr,
76 struct ktc_encryptionKey key, session;
77 struct rx_securityClass *tclass;
82 /* first, find the right key and kvno to use */
83 code = afsconf_GetLatestKey(adir, &kvno, &key);
85 return QuickAuth(astr, aindex);
88 /* next create random session key, using key for seed to good random */
89 DES_init_random_number_generator((DES_cblock *) &key);
90 code = DES_new_random_key((DES_cblock *) &session);
92 return QuickAuth(astr, aindex);
95 /* now create the actual ticket */
96 ticketLen = sizeof(tbuffer);
97 memset(tbuffer, '\0', sizeof(tbuffer));
99 tkt_MakeTicket(tbuffer, &ticketLen, &key, AUTH_SUPERUSER, "", "", 0,
100 0xffffffff, &session, 0, "afs", "");
101 /* parms were buffer, ticketlen, key to seal ticket with, principal
102 * name, instance and cell, start time, end time, session key to seal
103 * in ticket, inet host, server name and server instance */
105 return QuickAuth(astr, aindex);
108 /* Next, we have ticket, kvno and session key, authenticate the connection.
109 * We use a magic # instead of a constant because of basic compilation
110 * order when compiling the system from scratch (rx/rxkad.h isn't installed
112 tclass = (struct rx_securityClass *)
113 rxkad_NewClientSecurityObject(enclevel, &session, kvno, ticketLen,
116 *aindex = RX_SECIDX_KAD;
120 /* build a fake ticket for 'afs' using keys from adir, returning an
121 * appropriate security class and index
124 afsconf_ClientAuth(void *arock, struct rx_securityClass ** astr,
127 struct afsconf_dir * adir = (struct afsconf_dir *) arock;
131 rc = GenericAuth(adir, astr, aindex, rxkad_clear);
136 /* build a fake ticket for 'afs' using keys from adir, returning an
137 * appropriate security class and index. This one, unlike the above,
138 * tells rxkad to encrypt the data, too.
141 afsconf_ClientAuthSecure(void *arock,
142 struct rx_securityClass **astr,
145 struct afsconf_dir *adir = (struct afsconf_dir *) arock;
149 rc = GenericAuth(adir, astr, aindex, rxkad_crypt);
155 * Build a security class from the user's current tokens
157 * This function constructs an RX security class from a user's current
160 * @param[in] info The cell information structure
161 * @param[in] flags Security flags describing the desired mechanism
162 * @param[out] sc The selected security class
163 * @param[out] scIndex The index of the selected class
164 * @parma[out] expires The expiry time of the tokens used to build the class
166 * Only the AFSCONF_SECOPTS_ALWAYSENCRYPT flag will modify the behaviour of
167 * this function - it determines whether a cleartext, or encrypting, security
171 * 0 on success, non-zero on failure. An error code of
172 * AFSCONF_NO_SECURITY_CLASS indicates that were were unable to build a
173 * security class using the selected tokens.
177 afsconf_ClientAuthToken(struct afsconf_cell *info,
178 afsconf_secflags flags,
179 struct rx_securityClass **sc,
183 struct ktc_setTokenData *tokenSet = NULL;
184 struct ktc_token ttoken;
189 *scIndex = RX_SECIDX_NULL;
191 code = ktc_GetTokenEx(info->name, &tokenSet);
195 code = token_extractRxkad(tokenSet, &ttoken, NULL, NULL);
197 /* XXX - We should think about how to handle this */
198 if (ttoken.kvno < 0 || ttoken.kvno > 256) {
200 "funny kvno (%d) in ticket, proceeding\n",
203 if (flags & AFSCONF_SECOPTS_ALWAYSENCRYPT)
204 encryptLevel = rxkad_crypt;
206 encryptLevel = rxkad_clear;
207 *sc = rxkad_NewClientSecurityObject(encryptLevel,
212 *scIndex = RX_SECIDX_KAD;
214 *expires = ttoken.endTime;
218 token_FreeSet(&tokenSet);
221 return AFSCONF_NO_SECURITY_CLASS;
227 * Set the security flags to be used for a particular configuration
230 afsconf_SetSecurityFlags(struct afsconf_dir *dir,
231 afsconf_secflags flags)
233 dir->securityFlags = flags;
237 * Build a set of security classes suitable for a server accepting
238 * incoming connections
240 #if !defined(UKERNEL)
242 afsconf_BuildServerSecurityObjects(void *rock,
243 struct rx_securityClass ***classes,
244 afs_int32 *numClasses)
246 struct afsconf_dir *dir = rock;
248 if (dir->securityFlags & AFSCONF_SECOPTS_ALWAYSENCRYPT)
253 *classes = calloc(*numClasses, sizeof(**classes));
255 (*classes)[0] = rxnull_NewServerSecurityObject();
256 (*classes)[1] = NULL;
257 (*classes)[2] = rxkad_NewServerSecurityObject(0, dir,
258 afsconf_GetKey, NULL);
260 if (dir->securityFlags & AFSCONF_SECOPTS_ALWAYSENCRYPT)
261 (*classes)[3] = rxkad_NewServerSecurityObject(rxkad_crypt, dir,
262 afsconf_GetKey, NULL);
267 * Pick a security class to use for an outgoing connection
269 * This function selects an RX security class to use for an outgoing
270 * connection, based on the set of security flags provided.
273 * The configuration directory structure for this cell. If NULL,
274 * no classes requiring local configuration will be returned.
276 * A set of flags to determine the properties of the security class which
278 * - AFSCONF_SECOPTS_NOAUTH - return an anonymous secirty class
279 * - AFSCONF_SECOPTS_LOCALAUTH - use classes which have local key
280 * material available.
281 * - AFSCONF_SECOPTS_ALWAYSENCRYPT - use classes in encrypting, rather
282 * than authentication or integrity modes.
283 * - AFSCONF_SECOPTS_FALLBACK_NULL - if no suitable class can be found,
284 * then fallback to the rxnull security class.
286 * The cell information structure for the current cell. If this is NULL,
287 * then use a version locally obtained using the cellName.
288 * @param[in] cellName
289 * The cellName to use when obtaining cell information (may be NULL if
292 * The selected security class
293 * @param[out] scIndex
294 * The index of the selected security class
295 * @param[out] expires
296 * The expiry time of the tokens used to construct the class. Will be
297 * NEVER_DATE if the class has an unlimited lifetime. If NULL, the
298 * function won't store the expiry date.
301 * Returns 0 on success, or a com_err error code on failure.
304 afsconf_PickClientSecObj(struct afsconf_dir *dir, afsconf_secflags flags,
305 struct afsconf_cell *info,
306 char *cellName, struct rx_securityClass **sc,
307 afs_int32 *scIndex, time_t *expires) {
308 struct afsconf_cell localInfo;
312 *scIndex = RX_SECIDX_NULL;
316 if ( !(flags & AFSCONF_SECOPTS_NOAUTH) ) {
318 return AFSCONF_NOCELLDB;
320 if (flags & AFSCONF_SECOPTS_LOCALAUTH) {
321 if (flags & AFSCONF_SECOPTS_ALWAYSENCRYPT)
322 code = afsconf_ClientAuthSecure(dir, sc, scIndex);
324 code = afsconf_ClientAuth(dir, sc, scIndex);
329 /* The afsconf_ClientAuth functions will fall back to giving
330 * a rxnull object, which we don't want if localauth has been
331 * explicitly requested. Check for this, and bail out if we
332 * get one. Note that this leaks a security object at present
334 if (*scIndex == RX_SECIDX_NULL) {
336 code = AFSCONF_NOTFOUND;
341 *expires = NEVERDATE;
344 code = afsconf_GetCellInfo(dir, cellName, NULL, &localInfo);
350 code = afsconf_ClientAuthToken(info, flags, sc, scIndex, expires);
351 if (code && !(flags & AFSCONF_SECOPTS_FALLBACK_NULL))
354 /* If we didn't get a token, we'll just run anonymously */
359 *sc = rxnull_NewClientSecurityObject();
360 *scIndex = RX_SECIDX_NULL;
362 *expires = NEVERDATE;