@@ -13,7 +13,10 @@ Major new features:
Deprecated and removed features, and other changes affecting compatibility:
- [Add deprecations, removals and changes affecting compatibility here]
+* The compatibility functions getpublickey, getsecretkey,
+ authdes_create. The _authenticate compatibility function and the Sun
+ RPC server reject DES authentication attempts with an AUTH_TOOWEAK
+ error.
Changes to build and runtime requirements:
@@ -11,11 +11,6 @@ libc_hidden_proto (rtime)
extern bool_t xdr_authdes_cred (XDR *xdrs, struct authdes_cred *cred);
extern bool_t xdr_authdes_verf (XDR *xdrs,
struct authdes_verf *verf);
-struct svc_req;
-struct rpc_msg;
-extern enum auth_stat _svcauth_des (struct svc_req *rqst,
- struct rpc_msg *msg);
-
libc_hidden_proto (authdes_getucred)
libc_hidden_proto (xdr_authdes_cred)
@@ -101,8 +101,6 @@ libc {
_nss_files_getsgnam_r;
_nss_netgroup_parseline;
- _nss_files_getpublickey;
- _nss_files_getsecretkey;
_nss_files_initgroups_dyn;
@@ -53,14 +53,12 @@ DEFINE_NSS_FUNCTION (getntohost_r)
DEFINE_NSS_FUNCTION (getprotobyname_r)
DEFINE_NSS_FUNCTION (getprotobynumber_r)
DEFINE_NSS_FUNCTION (getprotoent_r)
-DEFINE_NSS_FUNCTION (getpublickey)
DEFINE_NSS_FUNCTION (getpwent_r)
DEFINE_NSS_FUNCTION (getpwnam_r)
DEFINE_NSS_FUNCTION (getpwuid_r)
DEFINE_NSS_FUNCTION (getrpcbyname_r)
DEFINE_NSS_FUNCTION (getrpcbynumber_r)
DEFINE_NSS_FUNCTION (getrpcent_r)
-DEFINE_NSS_FUNCTION (getsecretkey)
DEFINE_NSS_FUNCTION (getservbyname_r)
DEFINE_NSS_FUNCTION (getservbyport_r)
DEFINE_NSS_FUNCTION (getservent_r)
@@ -142,7 +142,6 @@ typedef enum nss_status nss_getprotobynumber_r (int, struct protoent *,
char *, size_t, int *);
typedef enum nss_status nss_getprotoent_r (struct protoent *,
char *, size_t, int *);
-typedef enum nss_status nss_getpublickey (const char *, char *, int *);
typedef enum nss_status nss_getpwent_r (struct passwd *,
char *, size_t, int *);
typedef enum nss_status nss_getpwnam_r (const char *, struct passwd *,
@@ -155,7 +154,6 @@ typedef enum nss_status nss_getrpcbynumber_r (int, struct rpcent *,
char *, size_t, int *);
typedef enum nss_status nss_getrpcent_r (struct rpcent *,
char *, size_t, int *);
-typedef enum nss_status nss_getsecretkey (const char *, char *, char *, int *);
typedef enum nss_status nss_getservbyname_r (const char *, const char *,
struct servent *, char *, size_t,
int *);
@@ -226,14 +224,12 @@ typedef enum nss_status nss_setspent (int);
extern nss_getprotobyname_r _nss_##module##_getprotobyname_r; \
extern nss_getprotobynumber_r _nss_##module##_getprotobynumber_r; \
extern nss_getprotoent_r _nss_##module##_getprotoent_r; \
- extern nss_getpublickey _nss_##module##_getpublickey; \
extern nss_getpwent_r _nss_##module##_getpwent_r; \
extern nss_getpwnam_r _nss_##module##_getpwnam_r; \
extern nss_getpwuid_r _nss_##module##_getpwuid_r; \
extern nss_getrpcbyname_r _nss_##module##_getrpcbyname_r; \
extern nss_getrpcbynumber_r _nss_##module##_getrpcbynumber_r; \
extern nss_getrpcent_r _nss_##module##_getrpcent_r; \
- extern nss_getsecretkey _nss_##module##_getsecretkey; \
extern nss_getservbyname_r _nss_##module##_getservbyname_r; \
extern nss_getservbyport_r _nss_##module##_getservbyport_r; \
extern nss_getservent_r _nss_##module##_getservent_r; \
@@ -27,8 +27,6 @@ __nss_files_functions (nss_module_functions_untyped pointers)
/* Functions which are not implemented. */
#define _nss_files_getcanonname_r NULL
#define _nss_files_gethostbyaddr2_r NULL
-#define _nss_files_getpublickey NULL
-#define _nss_files_getsecretkey NULL
#define _nss_files_netname2user NULL
#undef DEFINE_NSS_FUNCTION
@@ -32,6 +32,7 @@
* auth_des.c, client-side implementation of DES authentication
*/
+#include <errno.h>
#include <string.h>
#include <stdint.h>
#include <rpc/des_crypt.h>
@@ -106,15 +107,8 @@ authdes_create (const char *servername, u_int window,
/* syncaddr - optional addr of host to sync with */
/* ckey - optional conversation key to use */
{
- char pkey_data[1024];
- netobj pkey;
-
- if (!getpublickey (servername, pkey_data))
- return NULL;
-
- pkey.n_bytes = pkey_data;
- pkey.n_len = strlen (pkey_data) + 1;
- return authdes_pk_create (servername, &pkey, window, syncaddr, ckey);
+ __set_errno (ENOENT);
+ return NULL;
}
#ifdef EXPORT_RPC_SYMBOLS
libc_hidden_def (authdes_create)
@@ -17,41 +17,14 @@
<https://www.gnu.org/licenses/>. */
#include <errno.h>
-#include <rpc/netdb.h>
#include <rpc/auth_des.h>
#include <shlib-compat.h>
-#include "nsswitch.h"
-
-
-/* Type of the lookup function for the public key. */
-typedef int (*public_function) (const char *, char *, int *);
-
-/* Type of the lookup function for the secret key. */
-typedef int (*secret_function) (const char *, char *, const char *, int *);
-
int
getpublickey (const char *name, char *key)
{
- nss_action_list nip;
- union
- {
- public_function f;
- void *ptr;
- } fct;
- enum nss_status status = NSS_STATUS_UNAVAIL;
- int no_more;
-
- no_more = __nss_publickey_lookup2 (&nip, "getpublickey", NULL, &fct.ptr);
-
- while (! no_more)
- {
- status = (*fct.f) (name, key, &errno);
-
- no_more = __nss_next2 (&nip, "getpublickey", NULL, &fct.ptr, status, 0);
- }
-
- return status == NSS_STATUS_SUCCESS;
+ __set_errno (ENOENT);
+ return 0;
}
libc_hidden_nolink_sunrpc (getpublickey, GLIBC_2_0)
@@ -59,24 +32,7 @@ libc_hidden_nolink_sunrpc (getpublickey, GLIBC_2_0)
int
getsecretkey (const char *name, char *key, const char *passwd)
{
- nss_action_list nip;
- union
- {
- secret_function f;
- void *ptr;
- } fct;
- enum nss_status status = NSS_STATUS_UNAVAIL;
- int no_more;
-
- no_more = __nss_publickey_lookup2 (&nip, "getsecretkey", NULL, &fct.ptr);
-
- while (! no_more)
- {
- status = (*fct.f) (name, key, passwd, &errno);
-
- no_more = __nss_next2 (&nip, "getsecretkey", NULL, &fct.ptr, status, 0);
- }
-
- return status == NSS_STATUS_SUCCESS;
+ __set_errno (ENOENT);
+ return 0;
}
libc_hidden_nolink_sunrpc (getsecretkey, GLIBC_2_0)
@@ -57,22 +57,6 @@ extern enum auth_stat _svcauth_unix (struct svc_req *, struct rpc_msg *);
/* unix style (uid, gids) */
extern enum auth_stat _svcauth_short (struct svc_req *, struct rpc_msg *);
/* short hand unix style */
-extern enum auth_stat _svcauth_des (struct svc_req *, struct rpc_msg *);
- /* des style */
-
-static const struct
- {
- enum auth_stat (*authenticator) (struct svc_req *, struct rpc_msg *);
- }
-svcauthsw[] =
-{
- { _svcauth_null }, /* AUTH_NULL */
- { _svcauth_unix }, /* AUTH_UNIX */
- { _svcauth_short }, /* AUTH_SHORT */
- { _svcauth_des } /* AUTH_DES */
-};
-#define AUTH_MAX 3 /* HIGHEST AUTH NUMBER */
-
/*
* The call rpc message, msg has been obtained from the wire. The msg contains
@@ -88,9 +72,6 @@ svcauthsw[] =
* The caller still owns and is responsible for msg->u.cmb.cred and
* msg->u.cmb.verf. The authentication system retains ownership of
* rqst->rq_client_cred, the cooked credentials.
- *
- * There is an assumption that any flavour less than AUTH_NULL is
- * invalid.
*/
enum auth_stat
_authenticate (register struct svc_req *rqst, struct rpc_msg *msg)
@@ -101,9 +82,15 @@ _authenticate (register struct svc_req *rqst, struct rpc_msg *msg)
rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor;
rqst->rq_xprt->xp_verf.oa_length = 0;
cred_flavor = rqst->rq_cred.oa_flavor;
- if ((cred_flavor <= AUTH_MAX) && (cred_flavor >= AUTH_NULL))
- return (*(svcauthsw[cred_flavor].authenticator)) (rqst, msg);
-
+ switch (cred_flavor)
+ {
+ case AUTH_NULL:
+ return _svcauth_null (rqst, msg);
+ case AUTH_UNIX:
+ return _svcauth_unix (rqst, msg);
+ case AUTH_SHORT:
+ return _svcauth_short (rqst, msg);
+ }
return AUTH_REJECTEDCRED;
}
libc_hidden_nolink_sunrpc (_authenticate, GLIBC_2_1)
@@ -75,13 +75,6 @@ struct cache_entry
#define authdes_cache RPC_THREAD_VARIABLE(authdes_cache_s)
#define authdes_lru RPC_THREAD_VARIABLE(authdes_lru_s)
-static void cache_init (void); /* initialize the cache */
-static short cache_spot (des_block *, char *, struct rpc_timeval *);
- /* find an entry in the cache */
-static void cache_ref (uint32_t sid); /* note that sid was ref'd */
-
-static void invalidate (char *cred); /* invalidate entry in cache */
-
/* Cache statistics. Accidental historic export without a matching
declaration in any header file. */
#ifndef SHARED
@@ -98,381 +91,6 @@ svcauthdes_stats;
compat_symbol (libc, svcauthdes_stats, svcauthdes_stats, GLIBC_2_0);
#endif
-/*
- * Service side authenticator for AUTH_DES
- */
-enum auth_stat
-_svcauth_des (register struct svc_req *rqst, register struct rpc_msg *msg)
-{
- register uint32_t *ixdr;
- des_block cryptbuf[2];
- register struct authdes_cred *cred;
- struct authdes_verf verf;
- int status;
- register struct cache_entry *entry;
- uint32_t sid = 0;
- des_block *sessionkey;
- des_block ivec;
- u_int window;
- struct rpc_timeval timestamp;
- uint32_t namelen;
- struct area
- {
- struct authdes_cred area_cred;
- char area_netname[MAXNETNAMELEN + 1];
- }
- *area;
-
- if (authdes_cache == NULL)
- cache_init ();
- if (authdes_cache == NULL) /* No free memory */
- return AUTH_FAILED;
-
- area = (struct area *) rqst->rq_clntcred;
- cred = (struct authdes_cred *) &area->area_cred;
-
- /*
- * Get the credential
- */
- if (msg->rm_call.cb_cred.oa_length <= 0 ||
- msg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES)
- return AUTH_BADCRED;
-
- ixdr = (uint32_t *) msg->rm_call.cb_cred.oa_base;
- cred->adc_namekind = IXDR_GET_ENUM (ixdr, enum authdes_namekind);
- switch (cred->adc_namekind)
- {
- case ADN_FULLNAME:
- namelen = IXDR_GET_U_INT32 (ixdr);
- if (namelen > MAXNETNAMELEN)
- {
- return AUTH_BADCRED;
- }
- cred->adc_fullname.name = area->area_netname;
- memcpy (cred->adc_fullname.name, (char *) ixdr, namelen);
- cred->adc_fullname.name[namelen] = 0;
- ixdr += (RNDUP (namelen) / BYTES_PER_XDR_UNIT);
- cred->adc_fullname.key.key.high = *ixdr++;
- cred->adc_fullname.key.key.low = *ixdr++;
- cred->adc_fullname.window = *ixdr++;
- break;
- case ADN_NICKNAME:
- cred->adc_nickname = *ixdr++;
- break;
- default:
- return AUTH_BADCRED;
- }
-
- /*
- * Get the verifier
- */
- if (msg->rm_call.cb_verf.oa_length <= 0 ||
- msg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES)
- return AUTH_BADCRED;
-
- ixdr = (uint32_t *) msg->rm_call.cb_verf.oa_base;
- verf.adv_xtimestamp.key.high = *ixdr++;
- verf.adv_xtimestamp.key.low = *ixdr++;
- verf.adv_int_u = *ixdr++;
-
- /*
- * Get the conversation key
- */
- if (cred->adc_namekind == ADN_FULLNAME)
- {
- netobj pkey;
- char pkey_data[1024];
-
- sessionkey = &cred->adc_fullname.key;
- if (!getpublickey (cred->adc_fullname.name, pkey_data))
- {
- debug("getpublickey");
- return AUTH_BADCRED;
- }
- pkey.n_bytes = pkey_data;
- pkey.n_len = strlen (pkey_data) + 1;
- if (key_decryptsession_pk (cred->adc_fullname.name, &pkey,
- sessionkey) < 0)
- {
- debug ("decryptsessionkey");
- return AUTH_BADCRED; /* key not found */
- }
- }
- else
- { /* ADN_NICKNAME */
- if (cred->adc_nickname >= AUTHDES_CACHESZ)
- {
- debug ("bad nickname");
- return AUTH_BADCRED; /* garbled credential */
- }
- else
- sid = cred->adc_nickname;
-
- /* XXX This could be wrong, but else we have a
- security problem */
- if (authdes_cache[sid].rname == NULL)
- return AUTH_BADCRED;
- sessionkey = &authdes_cache[sid].key;
- }
-
-
- /*
- * Decrypt the timestamp
- */
- cryptbuf[0] = verf.adv_xtimestamp;
- if (cred->adc_namekind == ADN_FULLNAME)
- {
- cryptbuf[1].key.high = cred->adc_fullname.window;
- cryptbuf[1].key.low = verf.adv_winverf;
- ivec.key.high = ivec.key.low = 0;
- status = cbc_crypt ((char *) sessionkey, (char *) cryptbuf,
- 2 * sizeof (des_block), DES_DECRYPT | DES_HW,
- (char *) &ivec);
- }
- else
- status = ecb_crypt ((char *) sessionkey, (char *) cryptbuf,
- sizeof (des_block), DES_DECRYPT | DES_HW);
-
- if (DES_FAILED (status))
- {
- debug ("decryption failure");
- return AUTH_FAILED; /* system error */
- }
-
- /*
- * XDR the decrypted timestamp
- */
- ixdr = (uint32_t *) cryptbuf;
- timestamp.tv_sec = IXDR_GET_INT32 (ixdr);
- timestamp.tv_usec = IXDR_GET_INT32 (ixdr);
-
- /*
- * Check for valid credentials and verifiers.
- * They could be invalid because the key was flushed
- * out of the cache, and so a new session should begin.
- * Be sure and send AUTH_REJECTED{CRED, VERF} if this is the case.
- */
- {
- struct timeval current;
- int nick;
- u_int winverf;
-
- if (cred->adc_namekind == ADN_FULLNAME)
- {
- short tmp_spot;
-
- window = IXDR_GET_U_INT32 (ixdr);
- winverf = IXDR_GET_U_INT32 (ixdr);
- if (winverf != window - 1)
- {
- debug ("window verifier mismatch");
- return AUTH_BADCRED; /* garbled credential */
- }
- tmp_spot = cache_spot (sessionkey, cred->adc_fullname.name,
- ×tamp);
- if (tmp_spot < 0 || tmp_spot > AUTHDES_CACHESZ)
- {
- debug ("replayed credential");
- return AUTH_REJECTEDCRED; /* replay */
- }
- sid = tmp_spot;
- nick = 0;
- }
- else
- { /* ADN_NICKNAME */
- window = authdes_cache[sid].window;
- nick = 1;
- }
-
- if (timestamp.tv_usec >= USEC_PER_SEC)
- {
- debug ("invalid usecs");
- /* cached out (bad key), or garbled verifier */
- return nick ? AUTH_REJECTEDVERF : AUTH_BADVERF;
- }
- if (nick && BEFORE (×tamp, &authdes_cache[sid].laststamp))
- {
- debug ("timestamp before last seen");
- return AUTH_REJECTEDVERF; /* replay */
- }
- {
- struct timespec now;
- __clock_gettime (CLOCK_REALTIME, &now);
- TIMESPEC_TO_TIMEVAL (¤t, &now);
- }
- current.tv_sec -= window; /* allow for expiration */
- if (!BEFORE (¤t, ×tamp))
- {
- debug ("timestamp expired");
- /* replay, or garbled credential */
- return nick ? AUTH_REJECTEDVERF : AUTH_BADCRED;
- }
- }
-
- /*
- * Set up the reply verifier
- */
- verf.adv_nickname = sid;
-
- /*
- * xdr the timestamp before encrypting
- */
- ixdr = (uint32_t *) cryptbuf;
- IXDR_PUT_INT32 (ixdr, timestamp.tv_sec - 1);
- IXDR_PUT_INT32 (ixdr, timestamp.tv_usec);
-
- /*
- * encrypt the timestamp
- */
- status = ecb_crypt ((char *) sessionkey, (char *) cryptbuf,
- sizeof (des_block), DES_ENCRYPT | DES_HW);
- if (DES_FAILED (status))
- {
- debug ("encryption failure");
- return AUTH_FAILED; /* system error */
- }
- verf.adv_xtimestamp = cryptbuf[0];
-
- /*
- * Serialize the reply verifier, and update rqst
- */
- ixdr = (uint32_t *) msg->rm_call.cb_verf.oa_base;
- *ixdr++ = verf.adv_xtimestamp.key.high;
- *ixdr++ = verf.adv_xtimestamp.key.low;
- *ixdr++ = verf.adv_int_u;
-
- rqst->rq_xprt->xp_verf.oa_flavor = AUTH_DES;
- rqst->rq_xprt->xp_verf.oa_base = msg->rm_call.cb_verf.oa_base;
- rqst->rq_xprt->xp_verf.oa_length =
- (char *) ixdr - msg->rm_call.cb_verf.oa_base;
-
- /*
- * We succeeded, commit the data to the cache now and
- * finish cooking the credential.
- */
- entry = &authdes_cache[sid];
- entry->laststamp = timestamp;
- cache_ref (sid);
- if (cred->adc_namekind == ADN_FULLNAME)
- {
- size_t full_len;
-
- cred->adc_fullname.window = window;
- cred->adc_nickname = sid; /* save nickname */
- if (entry->rname != NULL)
- mem_free (entry->rname, strlen (entry->rname) + 1);
- full_len = strlen (cred->adc_fullname.name) + 1;
- entry->rname = mem_alloc ((u_int) full_len);
- if (entry->rname != NULL)
- memcpy (entry->rname, cred->adc_fullname.name, full_len);
- else
- {
- debug ("out of memory");
- return AUTH_FAILED; /* out of memory is bad */
- }
- entry->key = *sessionkey;
- entry->window = window;
- invalidate (entry->localcred); /* mark any cached cred invalid */
- }
- else
- { /* ADN_NICKNAME */
- /*
- * nicknames are cooked into fullnames
- */
- cred->adc_namekind = ADN_FULLNAME;
- cred->adc_fullname.name = entry->rname;
- cred->adc_fullname.key = entry->key;
- cred->adc_fullname.window = entry->window;
- }
- return AUTH_OK; /* we made it! */
-}
-
-
-/*
- * Initialize the cache
- */
-static void
-cache_init (void)
-{
- register int i;
-
- authdes_cache = (struct cache_entry *)
- calloc (sizeof (struct cache_entry) * AUTHDES_CACHESZ, 1);
- if (authdes_cache == NULL)
- return;
-
- authdes_lru = (int *) mem_alloc (sizeof (int) * AUTHDES_CACHESZ);
- /*
- * Initialize the lru list
- */
- for (i = 0; i < AUTHDES_CACHESZ; ++i)
- authdes_lru[i] = i;
-}
-
-
-/*
- * Find the lru victim
- */
-static short
-cache_victim (void)
-{
- return authdes_lru[AUTHDES_CACHESZ - 1];
-}
-
-/*
- * Note that sid was referenced
- */
-static void
-cache_ref (register uint32_t sid)
-{
- register int i;
- register int curr;
- register int prev;
-
- prev = authdes_lru[0];
- authdes_lru[0] = sid;
- for (i = 1; prev != sid; ++i)
- {
- curr = authdes_lru[i];
- authdes_lru[i] = prev;
- prev = curr;
- }
-}
-
-/*
- * Find a spot in the cache for a credential containing
- * the items given. Return -1 if a replay is detected, otherwise
- * return the spot in the cache.
- */
-static short
-cache_spot (register des_block *key, char *name,
- struct rpc_timeval *timestamp)
-{
- register struct cache_entry *cp;
- register int i;
- register uint32_t hi;
-
- hi = key->key.high;
- for (cp = authdes_cache, i = 0; i < AUTHDES_CACHESZ; ++i, ++cp)
- {
- if (cp->key.key.high == hi &&
- cp->key.key.low == key->key.low &&
- cp->rname != NULL &&
- memcmp (cp->rname, name, strlen (name) + 1) == 0)
- {
- if (BEFORE (timestamp, &cp->laststamp))
- {
- ++svcauthdes_stats.ncachereplays;
- return -1; /* replay */
- }
- ++svcauthdes_stats.ncachehits;
- return i; /* refresh */
- }
- }
- ++svcauthdes_stats.ncachemisses;
- return cache_victim (); /* new credential */
-}
-
/*
* Local credential handling stuff.
* NOTE: bsd unix dependent.
@@ -585,11 +203,3 @@ authdes_getucred (const struct authdes_cred *adc, uid_t * uid, gid_t * gid,
return 1;
}
libc_hidden_nolink_sunrpc (authdes_getucred, GLIBC_2_1)
-
-static void
-invalidate (char *cred)
-{
- if (cred == NULL)
- return;
- ((struct bsdcred *) cred)->grouplen = INVALID;
-}