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
;
45 static int _afsconf_GetRxkadKrb5Key(void *arock
, int kvno
, int enctype
, void *outkey
,
48 struct afsconf_dir
*adir
= arock
;
49 struct afsconf_typedKey
*kobj
;
50 struct rx_opaque
*keymat
;
51 afsconf_keyType tktype
;
55 code
= afsconf_GetKeyByTypes(adir
, afsconf_rxkad_krb5
, kvno
, enctype
, &kobj
);
58 afsconf_typedKey_values(kobj
, &tktype
, &tkvno
, &tenctype
, &keymat
);
59 if (*keylen
< keymat
->len
) {
60 afsconf_typedKey_put(&kobj
);
61 return AFSCONF_BADKEY
;
63 memcpy(outkey
, keymat
->val
, keymat
->len
);
64 *keylen
= keymat
->len
;
65 afsconf_typedKey_put(&kobj
);
70 /* Return an appropriate security class and index */
72 afsconf_ServerAuth(void *arock
,
73 struct rx_securityClass
**astr
,
76 struct afsconf_dir
*adir
= (struct afsconf_dir
*) arock
;
77 struct rx_securityClass
*tclass
;
80 tclass
= (struct rx_securityClass
*)
81 rxkad_NewKrb5ServerSecurityObject(0, adir
, afsconf_GetKey
,
82 _afsconf_GetRxkadKrb5Key
, NULL
);
85 *aindex
= RX_SECIDX_KAD
;
95 GenericAuth(struct afsconf_dir
*adir
,
96 struct rx_securityClass
**astr
,
100 int enctype_preflist
[]={18, 17, 23, 16, 0};
102 struct ktc_encryptionKey key
, session
;
103 struct rx_securityClass
*tclass
;
108 struct afsconf_typedKey
*kobj
;
109 struct rx_opaque
*keymat
;
112 /* first, find the right key and kvno to use */
114 et
= enctype_preflist
;
116 code
= afsconf_GetLatestKeyByTypes(adir
, afsconf_rxkad_krb5
, *et
,
119 afsconf_keyType tktype
;
121 afsconf_typedKey_values(kobj
, &tktype
, &kvno
, &tenctype
, &keymat
);
122 RAND_add(keymat
->val
, keymat
->len
, 0.0);
130 code
= afsconf_GetLatestKey(adir
, &kvno
, &key
);
132 return QuickAuth(astr
, aindex
);
134 /* next create random session key, using key for seed to good random */
135 DES_init_random_number_generator((DES_cblock
*) &key
);
137 code
= DES_new_random_key((DES_cblock
*) &session
);
140 afsconf_typedKey_put(&kobj
);
141 return QuickAuth(astr
, aindex
);
145 ticketLen
= sizeof(tbuffer
);
146 memset(tbuffer
, '\0', sizeof(tbuffer
));
148 tkt_MakeTicket5(tbuffer
, &ticketLen
, *et
, &kvno
, keymat
->val
,
149 keymat
->len
, AUTH_SUPERUSER
, "", "", 0, 0x7fffffff,
150 &session
, "afs", "");
151 afsconf_typedKey_put(&kobj
);
153 /* now create the actual ticket */
154 ticketLen
= sizeof(tbuffer
);
155 memset(tbuffer
, '\0', sizeof(tbuffer
));
157 tkt_MakeTicket(tbuffer
, &ticketLen
, &key
, AUTH_SUPERUSER
, "", "", 0,
158 0xffffffff, &session
, 0, "afs", "");
159 /* parms were buffer, ticketlen, key to seal ticket with, principal
160 * name, instance and cell, start time, end time, session key to seal
161 * in ticket, inet host, server name and server instance */
164 return QuickAuth(astr
, aindex
);
167 /* Next, we have ticket, kvno and session key, authenticate the connection.
168 * We use a magic # instead of a constant because of basic compilation
169 * order when compiling the system from scratch (rx/rxkad.h isn't installed
171 tclass
= (struct rx_securityClass
*)
172 rxkad_NewClientSecurityObject(enclevel
, &session
, kvno
, ticketLen
,
175 *aindex
= RX_SECIDX_KAD
;
179 /* build a fake ticket for 'afs' using keys from adir, returning an
180 * appropriate security class and index
183 afsconf_ClientAuth(void *arock
, struct rx_securityClass
** astr
,
186 struct afsconf_dir
* adir
= (struct afsconf_dir
*) arock
;
190 rc
= GenericAuth(adir
, astr
, aindex
, rxkad_clear
);
195 /* build a fake ticket for 'afs' using keys from adir, returning an
196 * appropriate security class and index. This one, unlike the above,
197 * tells rxkad to encrypt the data, too.
200 afsconf_ClientAuthSecure(void *arock
,
201 struct rx_securityClass
**astr
,
204 struct afsconf_dir
*adir
= (struct afsconf_dir
*) arock
;
208 rc
= GenericAuth(adir
, astr
, aindex
, rxkad_crypt
);
214 * Build a security class from the user's current tokens
216 * This function constructs an RX security class from a user's current
219 * @param[in] info The cell information structure
220 * @param[in] flags Security flags describing the desired mechanism
221 * @param[out] sc The selected security class
222 * @param[out] scIndex The index of the selected class
223 * @parma[out] expires The expiry time of the tokens used to build the class
225 * Only the AFSCONF_SECOPTS_ALWAYSENCRYPT flag will modify the behaviour of
226 * this function - it determines whether a cleartext, or encrypting, security
230 * 0 on success, non-zero on failure. An error code of
231 * AFSCONF_NO_SECURITY_CLASS indicates that were were unable to build a
232 * security class using the selected tokens.
236 afsconf_ClientAuthToken(struct afsconf_cell
*info
,
237 afsconf_secflags flags
,
238 struct rx_securityClass
**sc
,
242 struct ktc_setTokenData
*tokenSet
= NULL
;
243 struct ktc_token ttoken
;
248 *scIndex
= RX_SECIDX_NULL
;
250 code
= ktc_GetTokenEx(info
->name
, &tokenSet
);
254 code
= token_extractRxkad(tokenSet
, &ttoken
, NULL
, NULL
);
256 /* XXX - We should think about how to handle this */
257 if (ttoken
.kvno
< 0 || ttoken
.kvno
> 256) {
259 "funny kvno (%d) in ticket, proceeding\n",
262 if (flags
& AFSCONF_SECOPTS_ALWAYSENCRYPT
)
263 encryptLevel
= rxkad_crypt
;
265 encryptLevel
= rxkad_clear
;
266 *sc
= rxkad_NewClientSecurityObject(encryptLevel
,
271 *scIndex
= RX_SECIDX_KAD
;
273 *expires
= ttoken
.endTime
;
277 token_FreeSet(&tokenSet
);
280 return AFSCONF_NO_SECURITY_CLASS
;
286 * Set the security flags to be used for a particular configuration
289 afsconf_SetSecurityFlags(struct afsconf_dir
*dir
,
290 afsconf_secflags flags
)
292 dir
->securityFlags
= flags
;
296 * Build a set of security classes suitable for a server accepting
297 * incoming connections
300 afsconf_BuildServerSecurityObjects(void *rock
,
301 struct rx_securityClass
***classes
,
302 afs_int32
*numClasses
)
304 struct afsconf_dir
*dir
= rock
;
306 if (dir
->securityFlags
& AFSCONF_SECOPTS_ALWAYSENCRYPT
)
311 *classes
= calloc(*numClasses
, sizeof(**classes
));
313 (*classes
)[RX_SECIDX_NULL
] = rxnull_NewServerSecurityObject();
314 (*classes
)[RX_SECIDX_VAB
] = NULL
;
315 (*classes
)[RX_SECIDX_KAD
] =
316 rxkad_NewKrb5ServerSecurityObject(0, dir
, afsconf_GetKey
,
317 _afsconf_GetRxkadKrb5Key
, NULL
);
319 if (dir
->securityFlags
& AFSCONF_SECOPTS_ALWAYSENCRYPT
)
320 (*classes
)[RX_SECIDX_KAE
] =
321 rxkad_NewKrb5ServerSecurityObject(rxkad_crypt
, dir
, afsconf_GetKey
,
322 _afsconf_GetRxkadKrb5Key
, NULL
);
326 * Pick a security class to use for an outgoing connection
328 * This function selects an RX security class to use for an outgoing
329 * connection, based on the set of security flags provided.
332 * The configuration directory structure for this cell. If NULL,
333 * no classes requiring local configuration will be returned.
335 * A set of flags to determine the properties of the security class which
337 * - AFSCONF_SECOPTS_NOAUTH - return an anonymous secirty class
338 * - AFSCONF_SECOPTS_LOCALAUTH - use classes which have local key
339 * material available.
340 * - AFSCONF_SECOPTS_ALWAYSENCRYPT - use classes in encrypting, rather
341 * than authentication or integrity modes.
342 * - AFSCONF_SECOPTS_FALLBACK_NULL - if no suitable class can be found,
343 * then fallback to the rxnull security class.
345 * The cell information structure for the current cell. If this is NULL,
346 * then use a version locally obtained using the cellName.
347 * @param[in] cellName
348 * The cellName to use when obtaining cell information (may be NULL if
351 * The selected security class
352 * @param[out] scIndex
353 * The index of the selected security class
354 * @param[out] expires
355 * The expiry time of the tokens used to construct the class. Will be
356 * NEVER_DATE if the class has an unlimited lifetime. If NULL, the
357 * function won't store the expiry date.
360 * Returns 0 on success, or a com_err error code on failure.
363 afsconf_PickClientSecObj(struct afsconf_dir
*dir
, afsconf_secflags flags
,
364 struct afsconf_cell
*info
,
365 char *cellName
, struct rx_securityClass
**sc
,
366 afs_int32
*scIndex
, time_t *expires
) {
367 struct afsconf_cell localInfo
;
371 *scIndex
= RX_SECIDX_NULL
;
375 if ( !(flags
& AFSCONF_SECOPTS_NOAUTH
) ) {
377 return AFSCONF_NOCELLDB
;
379 if (flags
& AFSCONF_SECOPTS_LOCALAUTH
) {
380 if (flags
& AFSCONF_SECOPTS_ALWAYSENCRYPT
)
381 code
= afsconf_ClientAuthSecure(dir
, sc
, scIndex
);
383 code
= afsconf_ClientAuth(dir
, sc
, scIndex
);
388 /* The afsconf_ClientAuth functions will fall back to giving
389 * a rxnull object, which we don't want if localauth has been
390 * explicitly requested. Check for this, and bail out if we
391 * get one. Note that this leaks a security object at present
393 if (!(flags
& AFSCONF_SECOPTS_FALLBACK_NULL
) &&
394 *scIndex
== RX_SECIDX_NULL
) {
396 code
= AFSCONF_NOTFOUND
;
401 *expires
= NEVERDATE
;
404 code
= afsconf_GetCellInfo(dir
, cellName
, NULL
, &localInfo
);
410 code
= afsconf_ClientAuthToken(info
, flags
, sc
, scIndex
, expires
);
411 if (code
&& !(flags
& AFSCONF_SECOPTS_FALLBACK_NULL
))
414 /* If we didn't get a token, we'll just run anonymously */
419 *sc
= rxnull_NewClientSecurityObject();
420 *scIndex
= RX_SECIDX_NULL
;
422 *expires
= NEVERDATE
;