diff options
Diffstat (limited to 'lib')
37 files changed, 339 insertions, 1917 deletions
diff --git a/lib/libc/include/compat.h b/lib/libc/include/compat.h index 70fb8dcd97f3..97f22607ddd7 100644 --- a/lib/libc/include/compat.h +++ b/lib/libc/include/compat.h @@ -69,6 +69,9 @@ __sym_compat(kevent, freebsd11_kevent, FBSD_1.0); __sym_compat(swapoff, freebsd13_swapoff, FBSD_1.0); +__sym_compat(getgroups, freebsd14_getgroups, FBSD_1.0); +__sym_compat(setgroups, freebsd14_setgroups, FBSD_1.0); + #undef __sym_compat #define __weak_reference(sym,alias) \ diff --git a/lib/libc/rpc/Symbol.map b/lib/libc/rpc/Symbol.map index 105d6fb6b54e..61e8e084b1e0 100644 --- a/lib/libc/rpc/Symbol.map +++ b/lib/libc/rpc/Symbol.map @@ -8,13 +8,9 @@ FBSD_1.0 { xdr_desargs; xdr_desresp; - authdes_seccreate; - authdes_pk_seccreate; authnone_create; authunix_create; authunix_create_default; - xdr_authdes_cred; - xdr_authdes_verf; xdr_authunix_parms; bindresvport; bindresvport_sa; @@ -58,15 +54,6 @@ FBSD_1.0 { endrpcent; getrpcent; getrpcport; - key_setsecret; - key_secretkey_is_set; - key_encryptsession_pk; - key_decryptsession_pk; - key_encryptsession; - key_decryptsession; - key_gendes; - key_setnet; - key_get_conv; xdr_keystatus; xdr_keybuf; xdr_netnamestr; @@ -130,7 +117,6 @@ FBSD_1.0 { callrpc; registerrpc; clnt_broadcast; - authdes_create; clntunix_create; svcunix_create; svcunixfd_create; @@ -180,8 +166,6 @@ FBSD_1.0 { _authenticate; _svcauth_null; svc_auth_reg; - _svcauth_des; - authdes_getucred; _svcauth_unix; _svcauth_short; svc_dg_create; @@ -205,9 +189,6 @@ FBSD_1.8 { FBSDprivate_1.0 { __des_crypt_LOCAL; - __key_encryptsession_pk_LOCAL; - __key_decryptsession_pk_LOCAL; - __key_gendes_LOCAL; __svc_clean_idle; __rpc_gss_unwrap; __rpc_gss_unwrap_stub; diff --git a/lib/libc/rpc/auth_des.c b/lib/libc/rpc/auth_des.c index c9b20de25cda..754d55cbed3e 100644 --- a/lib/libc/rpc/auth_des.c +++ b/lib/libc/rpc/auth_des.c @@ -30,463 +30,34 @@ /* * Copyright (c) 1988 by Sun Microsystems, Inc. */ + /* - * auth_des.c, client-side implementation of DES authentication + * Secure RPC DES authentication was removed in FreeBSD 15.0. + * These symbols are provided for backward compatibility, but provide no + * functionality and will always return an error. */ #include "namespace.h" #include "reentrant.h" -#include <err.h> -#include <errno.h> -#include <string.h> -#include <stdlib.h> -#include <unistd.h> -#include <rpc/des_crypt.h> -#include <syslog.h> #include <rpc/types.h> #include <rpc/auth.h> #include <rpc/auth_des.h> -#include <rpc/clnt.h> -#include <rpc/xdr.h> -#include <sys/socket.h> -#undef NIS #include <rpcsvc/nis.h> #include "un-namespace.h" -#include "mt_misc.h" - -#define USEC_PER_SEC 1000000 -#define RTIME_TIMEOUT 5 /* seconds to wait for sync */ - -#define AUTH_PRIVATE(auth) (struct ad_private *) auth->ah_private -#define ALLOC(object_type) (object_type *) mem_alloc(sizeof(object_type)) -#define FREE(ptr, size) mem_free((char *)(ptr), (int) size) -#define ATTEMPT(xdr_op) if (!(xdr_op)) return (FALSE) - -extern bool_t xdr_authdes_cred( XDR *, struct authdes_cred *); -extern bool_t xdr_authdes_verf( XDR *, struct authdes_verf *); -extern int key_encryptsession_pk(char *, netobj *, des_block *); - -extern bool_t __rpc_get_time_offset(struct timeval *, nis_server *, char *, - char **, char **); -/* - * DES authenticator operations vector - */ -static void authdes_nextverf(AUTH *); -static bool_t authdes_marshal(AUTH *, XDR *); -static bool_t authdes_validate(AUTH *, struct opaque_auth *); -static bool_t authdes_refresh(AUTH *, void *); -static void authdes_destroy(AUTH *); - -static struct auth_ops *authdes_ops(void); - -/* - * This struct is pointed to by the ah_private field of an "AUTH *" - */ -struct ad_private { - char *ad_fullname; /* client's full name */ - u_int ad_fullnamelen; /* length of name, rounded up */ - char *ad_servername; /* server's full name */ - u_int ad_servernamelen; /* length of name, rounded up */ - u_int ad_window; /* client specified window */ - bool_t ad_dosync; /* synchronize? */ - struct netbuf ad_syncaddr; /* remote host to synch with */ - char *ad_timehost; /* remote host to synch with */ - struct timeval ad_timediff; /* server's time - client's time */ - u_int ad_nickname; /* server's nickname for client */ - struct authdes_cred ad_cred; /* storage for credential */ - struct authdes_verf ad_verf; /* storage for verifier */ - struct timeval ad_timestamp; /* timestamp sent */ - des_block ad_xkey; /* encrypted conversation key */ - u_char ad_pkey[1024]; /* Server's actual public key */ - char *ad_netid; /* Timehost netid */ - char *ad_uaddr; /* Timehost uaddr */ - nis_server *ad_nis_srvr; /* NIS+ server struct */ -}; - -AUTH *authdes_pk_seccreate(const char *, netobj *, u_int, const char *, - const des_block *, nis_server *); - -/* - * documented version of authdes_seccreate - */ -/* - servername: network name of server - win: time to live - timehost: optional hostname to sync with - ckey: optional conversation key to use -*/ - -AUTH * -authdes_seccreate(const char *servername, const u_int win, +static AUTH * +__authdes_seccreate(const char *servername, const u_int win, const char *timehost, const des_block *ckey) { - u_char pkey_data[1024]; - netobj pkey; - AUTH *dummy; - - if (! getpublickey(servername, (char *) pkey_data)) { - syslog(LOG_ERR, - "authdes_seccreate: no public key found for %s", - servername); - return (NULL); - } - - pkey.n_bytes = (char *) pkey_data; - pkey.n_len = (u_int)strlen((char *)pkey_data) + 1; - dummy = authdes_pk_seccreate(servername, &pkey, win, timehost, - ckey, NULL); - return (dummy); -} - -/* - * Slightly modified version of authdessec_create which takes the public key - * of the server principal as an argument. This spares us a call to - * getpublickey() which in the nameserver context can cause a deadlock. - */ -AUTH * -authdes_pk_seccreate(const char *servername, netobj *pkey, u_int window, - const char *timehost, const des_block *ckey, nis_server *srvr) -{ - AUTH *auth; - struct ad_private *ad; - char namebuf[MAXNETNAMELEN+1]; - - /* - * Allocate everything now - */ - auth = ALLOC(AUTH); - if (auth == NULL) { - syslog(LOG_ERR, "authdes_pk_seccreate: out of memory"); - return (NULL); - } - ad = ALLOC(struct ad_private); - if (ad == NULL) { - syslog(LOG_ERR, "authdes_pk_seccreate: out of memory"); - goto failed; - } - ad->ad_fullname = ad->ad_servername = NULL; /* Sanity reasons */ - ad->ad_timehost = NULL; - ad->ad_netid = NULL; - ad->ad_uaddr = NULL; - ad->ad_nis_srvr = NULL; - ad->ad_timediff.tv_sec = 0; - ad->ad_timediff.tv_usec = 0; - memcpy(ad->ad_pkey, pkey->n_bytes, pkey->n_len); - if (!getnetname(namebuf)) - goto failed; - ad->ad_fullnamelen = RNDUP((u_int) strlen(namebuf)); - ad->ad_fullname = (char *)mem_alloc(ad->ad_fullnamelen + 1); - ad->ad_servernamelen = strlen(servername); - ad->ad_servername = (char *)mem_alloc(ad->ad_servernamelen + 1); - - if (ad->ad_fullname == NULL || ad->ad_servername == NULL) { - syslog(LOG_ERR, "authdes_seccreate: out of memory"); - goto failed; - } - if (timehost != NULL) { - ad->ad_timehost = (char *)mem_alloc(strlen(timehost) + 1); - if (ad->ad_timehost == NULL) { - syslog(LOG_ERR, "authdes_seccreate: out of memory"); - goto failed; - } - memcpy(ad->ad_timehost, timehost, strlen(timehost) + 1); - ad->ad_dosync = TRUE; - } else if (srvr != NULL) { - ad->ad_nis_srvr = srvr; /* transient */ - ad->ad_dosync = TRUE; - } else { - ad->ad_dosync = FALSE; - } - memcpy(ad->ad_fullname, namebuf, ad->ad_fullnamelen + 1); - memcpy(ad->ad_servername, servername, ad->ad_servernamelen + 1); - ad->ad_window = window; - if (ckey == NULL) { - if (key_gendes(&auth->ah_key) < 0) { - syslog(LOG_ERR, - "authdes_seccreate: keyserv(1m) is unable to generate session key"); - goto failed; - } - } else { - auth->ah_key = *ckey; - } - - /* - * Set up auth handle - */ - auth->ah_cred.oa_flavor = AUTH_DES; - auth->ah_verf.oa_flavor = AUTH_DES; - auth->ah_ops = authdes_ops(); - auth->ah_private = (caddr_t)ad; - - if (!authdes_refresh(auth, NULL)) { - goto failed; - } - ad->ad_nis_srvr = NULL; /* not needed any longer */ - return (auth); - -failed: - if (auth) - FREE(auth, sizeof (AUTH)); - if (ad) { - if (ad->ad_fullname) - FREE(ad->ad_fullname, ad->ad_fullnamelen + 1); - if (ad->ad_servername) - FREE(ad->ad_servername, ad->ad_servernamelen + 1); - if (ad->ad_timehost) - FREE(ad->ad_timehost, strlen(ad->ad_timehost) + 1); - if (ad->ad_netid) - FREE(ad->ad_netid, strlen(ad->ad_netid) + 1); - if (ad->ad_uaddr) - FREE(ad->ad_uaddr, strlen(ad->ad_uaddr) + 1); - FREE(ad, sizeof (struct ad_private)); - } return (NULL); } +__sym_compat(authdes_seccreate, __authdes_seccreate, FBSD_1.0); -/* - * Implement the five authentication operations - */ - - -/* - * 1. Next Verifier - */ -/*ARGSUSED*/ -static void -authdes_nextverf(AUTH *auth __unused) +static AUTH * +__authdes_pk_seccreate(const char *servername __unused, netobj *pkey __unused, + u_int window __unused, const char *timehost __unused, + const des_block *ckey __unused, nis_server *srvr __unused) { - /* what the heck am I supposed to do??? */ -} - - -/* - * 2. Marshal - */ -static bool_t -authdes_marshal(AUTH *auth, XDR *xdrs) -{ -/* LINTED pointer alignment */ - struct ad_private *ad = AUTH_PRIVATE(auth); - struct authdes_cred *cred = &ad->ad_cred; - struct authdes_verf *verf = &ad->ad_verf; - des_block cryptbuf[2]; - des_block ivec; - int status; - int len; - rpc_inline_t *ixdr; - - /* - * Figure out the "time", accounting for any time difference - * with the server if necessary. - */ - (void)gettimeofday(&ad->ad_timestamp, NULL); - ad->ad_timestamp.tv_sec += ad->ad_timediff.tv_sec; - ad->ad_timestamp.tv_usec += ad->ad_timediff.tv_usec; - while (ad->ad_timestamp.tv_usec >= USEC_PER_SEC) { - ad->ad_timestamp.tv_usec -= USEC_PER_SEC; - ad->ad_timestamp.tv_sec++; - } - - /* - * XDR the timestamp and possibly some other things, then - * encrypt them. - */ - ixdr = (rpc_inline_t *)cryptbuf; - IXDR_PUT_INT32(ixdr, ad->ad_timestamp.tv_sec); - IXDR_PUT_INT32(ixdr, ad->ad_timestamp.tv_usec); - if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { - IXDR_PUT_U_INT32(ixdr, ad->ad_window); - IXDR_PUT_U_INT32(ixdr, ad->ad_window - 1); - ivec.key.high = ivec.key.low = 0; - status = cbc_crypt((char *)&auth->ah_key, (char *)cryptbuf, - (u_int) 2 * sizeof (des_block), - DES_ENCRYPT | DES_HW, (char *)&ivec); - } else { - status = ecb_crypt((char *)&auth->ah_key, (char *)cryptbuf, - (u_int) sizeof (des_block), - DES_ENCRYPT | DES_HW); - } - if (DES_FAILED(status)) { - syslog(LOG_ERR, "authdes_marshal: DES encryption failure"); - return (FALSE); - } - ad->ad_verf.adv_xtimestamp = cryptbuf[0]; - if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { - ad->ad_cred.adc_fullname.window = cryptbuf[1].key.high; - ad->ad_verf.adv_winverf = cryptbuf[1].key.low; - } else { - ad->ad_cred.adc_nickname = ad->ad_nickname; - ad->ad_verf.adv_winverf = 0; - } - - /* - * Serialize the credential and verifier into opaque - * authentication data. - */ - if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { - len = ((1 + 1 + 2 + 1)*BYTES_PER_XDR_UNIT + ad->ad_fullnamelen); - } else { - len = (1 + 1)*BYTES_PER_XDR_UNIT; - } - - if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) { - IXDR_PUT_INT32(ixdr, AUTH_DES); - IXDR_PUT_INT32(ixdr, len); - } else { - ATTEMPT(xdr_putint32(xdrs, (int *)&auth->ah_cred.oa_flavor)); - ATTEMPT(xdr_putint32(xdrs, &len)); - } - ATTEMPT(xdr_authdes_cred(xdrs, cred)); - - len = (2 + 1)*BYTES_PER_XDR_UNIT; - if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) { - IXDR_PUT_INT32(ixdr, AUTH_DES); - IXDR_PUT_INT32(ixdr, len); - } else { - ATTEMPT(xdr_putint32(xdrs, (int *)&auth->ah_verf.oa_flavor)); - ATTEMPT(xdr_putint32(xdrs, &len)); - } - ATTEMPT(xdr_authdes_verf(xdrs, verf)); - return (TRUE); -} - - -/* - * 3. Validate - */ -static bool_t -authdes_validate(AUTH *auth, struct opaque_auth *rverf) -{ -/* LINTED pointer alignment */ - struct ad_private *ad = AUTH_PRIVATE(auth); - struct authdes_verf verf; - int status; - uint32_t *ixdr; - des_block buf; - - if (rverf->oa_length != (2 + 1) * BYTES_PER_XDR_UNIT) { - return (FALSE); - } -/* LINTED pointer alignment */ - ixdr = (uint32_t *)rverf->oa_base; - buf.key.high = (uint32_t)*ixdr++; - buf.key.low = (uint32_t)*ixdr++; - verf.adv_int_u = (uint32_t)*ixdr++; - - /* - * Decrypt the timestamp - */ - status = ecb_crypt((char *)&auth->ah_key, (char *)&buf, - (u_int)sizeof (des_block), DES_DECRYPT | DES_HW); - - if (DES_FAILED(status)) { - syslog(LOG_ERR, "authdes_validate: DES decryption failure"); - return (FALSE); - } - - /* - * xdr the decrypted timestamp - */ -/* LINTED pointer alignment */ - ixdr = (uint32_t *)buf.c; - verf.adv_timestamp.tv_sec = IXDR_GET_INT32(ixdr) + 1; - verf.adv_timestamp.tv_usec = IXDR_GET_INT32(ixdr); - - /* - * validate - */ - if (bcmp((char *)&ad->ad_timestamp, (char *)&verf.adv_timestamp, - sizeof(struct timeval)) != 0) { - syslog(LOG_DEBUG, "authdes_validate: verifier mismatch"); - return (FALSE); - } - - /* - * We have a nickname now, let's use it - */ - ad->ad_nickname = verf.adv_nickname; - ad->ad_cred.adc_namekind = ADN_NICKNAME; - return (TRUE); -} - -/* - * 4. Refresh - */ -/*ARGSUSED*/ -static bool_t -authdes_refresh(AUTH *auth, void *dummy __unused) -{ -/* LINTED pointer alignment */ - struct ad_private *ad = AUTH_PRIVATE(auth); - struct authdes_cred *cred = &ad->ad_cred; - int ok; - netobj pkey; - - if (ad->ad_dosync) { - ok = __rpc_get_time_offset(&ad->ad_timediff, ad->ad_nis_srvr, - ad->ad_timehost, &(ad->ad_uaddr), - &(ad->ad_netid)); - if (! ok) { - /* - * Hope the clocks are synced! - */ - ad->ad_dosync = 0; - syslog(LOG_DEBUG, - "authdes_refresh: unable to synchronize clock"); - } - } - ad->ad_xkey = auth->ah_key; - pkey.n_bytes = (char *)(ad->ad_pkey); - pkey.n_len = (u_int)strlen((char *)ad->ad_pkey) + 1; - if (key_encryptsession_pk(ad->ad_servername, &pkey, &ad->ad_xkey) < 0) { - syslog(LOG_INFO, - "authdes_refresh: keyserv(1m) is unable to encrypt session key"); - return (FALSE); - } - cred->adc_fullname.key = ad->ad_xkey; - cred->adc_namekind = ADN_FULLNAME; - cred->adc_fullname.name = ad->ad_fullname; - return (TRUE); -} - - -/* - * 5. Destroy - */ -static void -authdes_destroy(AUTH *auth) -{ -/* LINTED pointer alignment */ - struct ad_private *ad = AUTH_PRIVATE(auth); - - FREE(ad->ad_fullname, ad->ad_fullnamelen + 1); - FREE(ad->ad_servername, ad->ad_servernamelen + 1); - if (ad->ad_timehost) - FREE(ad->ad_timehost, strlen(ad->ad_timehost) + 1); - if (ad->ad_netid) - FREE(ad->ad_netid, strlen(ad->ad_netid) + 1); - if (ad->ad_uaddr) - FREE(ad->ad_uaddr, strlen(ad->ad_uaddr) + 1); - FREE(ad, sizeof (struct ad_private)); - FREE(auth, sizeof(AUTH)); -} - -static struct auth_ops * -authdes_ops(void) -{ - static struct auth_ops ops; - - /* VARIABLES PROTECTED BY ops_lock: ops */ - - mutex_lock(&authdes_ops_lock); - if (ops.ah_nextverf == NULL) { - ops.ah_nextverf = authdes_nextverf; - ops.ah_marshal = authdes_marshal; - ops.ah_validate = authdes_validate; - ops.ah_refresh = authdes_refresh; - ops.ah_destroy = authdes_destroy; - } - mutex_unlock(&authdes_ops_lock); - return (&ops); + return (NULL); } +__sym_compat(authdes_pk_seccreate, __authdes_pk_seccreate, FBSD_1.0); diff --git a/lib/libc/rpc/authdes_prot.c b/lib/libc/rpc/authdes_prot.c index 79a0e5baa084..56b44daafe41 100644 --- a/lib/libc/rpc/authdes_prot.c +++ b/lib/libc/rpc/authdes_prot.c @@ -42,44 +42,16 @@ #include <rpc/auth_des.h> #include "un-namespace.h" -#define ATTEMPT(xdr_op) if (!(xdr_op)) return (FALSE) - -bool_t -xdr_authdes_cred(XDR *xdrs, struct authdes_cred *cred) +static bool_t +__xdr_authdes_cred(XDR *xdrs, void *cred) { - enum authdes_namekind *padc_namekind = &cred->adc_namekind; - /* - * Unrolled xdr - */ - ATTEMPT(xdr_enum(xdrs, (enum_t *) padc_namekind)); - switch (cred->adc_namekind) { - case ADN_FULLNAME: - ATTEMPT(xdr_string(xdrs, &cred->adc_fullname.name, - MAXNETNAMELEN)); - ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_fullname.key, - sizeof(des_block))); - ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_fullname.window, - sizeof(cred->adc_fullname.window))); - return (TRUE); - case ADN_NICKNAME: - ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_nickname, - sizeof(cred->adc_nickname))); - return (TRUE); - default: - return (FALSE); - } + return (FALSE); } +__sym_compat(xdr_authdes_cred, __xdr_authdes_cred, FBSD_1.0); - -bool_t -xdr_authdes_verf(XDR *xdrs, struct authdes_verf *verf) +static bool_t +__xdr_authdes_verf(XDR *xdrs, void *verf) { - /* - * Unrolled xdr - */ - ATTEMPT(xdr_opaque(xdrs, (caddr_t)&verf->adv_xtimestamp, - sizeof(des_block))); - ATTEMPT(xdr_opaque(xdrs, (caddr_t)&verf->adv_int_u, - sizeof(verf->adv_int_u))); - return (TRUE); + return (FALSE); } +__sym_compat(xdr_authdes_verf, __xdr_authdes_verf, FBSD_1.0); diff --git a/lib/libc/rpc/key_call.c b/lib/libc/rpc/key_call.c index 5c87881c815c..eb274fcfff36 100644 --- a/lib/libc/rpc/key_call.c +++ b/lib/libc/rpc/key_call.c @@ -32,426 +32,78 @@ */ /* - * key_call.c, Interface to keyserver - * - * setsecretkey(key) - set your secret key - * encryptsessionkey(agent, deskey) - encrypt a session key to talk to agent - * decryptsessionkey(agent, deskey) - decrypt ditto - * gendeskey(deskey) - generate a secure des key + * Secure RPC keyserver support was removed in FreeBSD 15.0. + * These symbols are provided for backward compatibility, but provide no + * functionality and will always return an error. */ #include "namespace.h" #include "reentrant.h" -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <errno.h> #include <rpc/rpc.h> -#include <rpc/auth.h> -#include <rpc/auth_unix.h> #include <rpc/key_prot.h> -#include <string.h> -#include <netconfig.h> -#include <sys/utsname.h> -#include <stdlib.h> -#include <signal.h> -#include <sys/wait.h> -#include <sys/fcntl.h> +#include <rpc/auth.h> #include "un-namespace.h" #include "mt_misc.h" - -#define KEY_TIMEOUT 5 /* per-try timeout in seconds */ -#define KEY_NRETRY 12 /* number of retries */ - -#ifdef DEBUG -#define debug(msg) (void) fprintf(stderr, "%s\n", msg); -#else -#define debug(msg) -#endif /* DEBUG */ - -/* - * Hack to allow the keyserver to use AUTH_DES (for authenticated - * NIS+ calls, for example). The only functions that get called - * are key_encryptsession_pk, key_decryptsession_pk, and key_gendes. - * - * The approach is to have the keyserver fill in pointers to local - * implementations of these functions, and to call those in key_call(). - */ - -cryptkeyres *(*__key_encryptsession_pk_LOCAL)(uid_t, void *arg) = 0; -cryptkeyres *(*__key_decryptsession_pk_LOCAL)(uid_t, void *arg) = 0; -des_block *(*__key_gendes_LOCAL)(uid_t, void *) = 0; - -static int key_call( u_long, xdrproc_t, void *, xdrproc_t, void *); - -int -key_setsecret(const char *secretkey) -{ - keystatus status; - - if (!key_call((u_long) KEY_SET, (xdrproc_t)xdr_keybuf, - (void *)secretkey, - (xdrproc_t)xdr_keystatus, &status)) { - return (-1); - } - if (status != KEY_SUCCESS) { - debug("set status is nonzero"); - return (-1); - } - return (0); -} - - -/* key_secretkey_is_set() returns 1 if the keyserver has a secret key - * stored for the caller's effective uid; it returns 0 otherwise - * - * N.B.: The KEY_NET_GET key call is undocumented. Applications shouldn't - * be using it, because it allows them to get the user's secret key. - */ - -int -key_secretkey_is_set(void) -{ - struct key_netstres kres; - - memset((void*)&kres, 0, sizeof (kres)); - if (key_call((u_long) KEY_NET_GET, (xdrproc_t)xdr_void, NULL, - (xdrproc_t)xdr_key_netstres, &kres) && - (kres.status == KEY_SUCCESS) && - (kres.key_netstres_u.knet.st_priv_key[0] != 0)) { - /* avoid leaving secret key in memory */ - memset(kres.key_netstres_u.knet.st_priv_key, 0, HEXKEYBYTES); - return (1); - } - return (0); -} - -int -key_encryptsession_pk(char *remotename, netobj *remotekey, des_block *deskey) -{ - cryptkeyarg2 arg; - cryptkeyres res; - - arg.remotename = remotename; - arg.remotekey = *remotekey; - arg.deskey = *deskey; - if (!key_call((u_long)KEY_ENCRYPT_PK, (xdrproc_t)xdr_cryptkeyarg2, &arg, - (xdrproc_t)xdr_cryptkeyres, &res)) { - return (-1); - } - if (res.status != KEY_SUCCESS) { - debug("encrypt status is nonzero"); - return (-1); - } - *deskey = res.cryptkeyres_u.deskey; - return (0); -} - -int -key_decryptsession_pk(char *remotename, netobj *remotekey, des_block *deskey) -{ - cryptkeyarg2 arg; - cryptkeyres res; - - arg.remotename = remotename; - arg.remotekey = *remotekey; - arg.deskey = *deskey; - if (!key_call((u_long)KEY_DECRYPT_PK, (xdrproc_t)xdr_cryptkeyarg2, &arg, - (xdrproc_t)xdr_cryptkeyres, &res)) { - return (-1); - } - if (res.status != KEY_SUCCESS) { - debug("decrypt status is nonzero"); - return (-1); - } - *deskey = res.cryptkeyres_u.deskey; - return (0); -} - -int -key_encryptsession(const char *remotename, des_block *deskey) +static int +__key_setsecret(const char *secretkey) { - cryptkeyarg arg; - cryptkeyres res; - - arg.remotename = (char *) remotename; - arg.deskey = *deskey; - if (!key_call((u_long)KEY_ENCRYPT, (xdrproc_t)xdr_cryptkeyarg, &arg, - (xdrproc_t)xdr_cryptkeyres, &res)) { - return (-1); - } - if (res.status != KEY_SUCCESS) { - debug("encrypt status is nonzero"); - return (-1); - } - *deskey = res.cryptkeyres_u.deskey; - return (0); + return (-1); } +__sym_compat(key_setsecret, __key_setsecret, FBSD_1.0); -int -key_decryptsession(const char *remotename, des_block *deskey) +static int +__key_secretkey_is_set(void) { - cryptkeyarg arg; - cryptkeyres res; - - arg.remotename = (char *) remotename; - arg.deskey = *deskey; - if (!key_call((u_long)KEY_DECRYPT, (xdrproc_t)xdr_cryptkeyarg, &arg, - (xdrproc_t)xdr_cryptkeyres, &res)) { - return (-1); - } - if (res.status != KEY_SUCCESS) { - debug("decrypt status is nonzero"); - return (-1); - } - *deskey = res.cryptkeyres_u.deskey; return (0); } +__sym_compat(key_secretkey_is_set, __key_secretkey_is_set, FBSD_1.0); -int -key_gendes(des_block *key) +static int +__key_encryptsession_pk(char *remotename, netobj *remotekey, des_block *deskey) { - if (!key_call((u_long)KEY_GEN, (xdrproc_t)xdr_void, NULL, - (xdrproc_t)xdr_des_block, key)) { - return (-1); - } - return (0); + return (-1); } +__sym_compat(key_encryptsession_pk, __key_encryptsession_pk, FBSD_1.0); -int -key_setnet(struct key_netstarg *arg) +static int +__key_decryptsession_pk(char *remotename, netobj *remotekey, des_block *deskey) { - keystatus status; - - - if (!key_call((u_long) KEY_NET_PUT, (xdrproc_t)xdr_key_netstarg, arg, - (xdrproc_t)xdr_keystatus, &status)){ - return (-1); - } - - if (status != KEY_SUCCESS) { - debug("key_setnet status is nonzero"); - return (-1); - } - return (1); + return (-1); } +__sym_compat(key_decryptsession_pk, __key_decryptsession_pk, FBSD_1.0); - -int -key_get_conv(char *pkey, des_block *deskey) +static int +__key_encryptsession(const char *remotename, des_block *deskey) { - cryptkeyres res; - - if (!key_call((u_long) KEY_GET_CONV, (xdrproc_t)xdr_keybuf, pkey, - (xdrproc_t)xdr_cryptkeyres, &res)) { - return (-1); - } - if (res.status != KEY_SUCCESS) { - debug("get_conv status is nonzero"); - return (-1); - } - *deskey = res.cryptkeyres_u.deskey; - return (0); + return (-1); } +__sym_compat(key_encryptsession, __key_encryptsession, FBSD_1.0); -struct key_call_private { - CLIENT *client; /* Client handle */ - pid_t pid; /* process-id at moment of creation */ - uid_t uid; /* user-id at last authorization */ -}; -static struct key_call_private *key_call_private_main = NULL; -static thread_key_t key_call_key; -static once_t key_call_once = ONCE_INITIALIZER; -static int key_call_key_error; - -static void -key_call_destroy(void *vp) +static int +__key_decryptsession(const char *remotename, des_block *deskey) { - struct key_call_private *kcp = (struct key_call_private *)vp; - - if (kcp) { - if (kcp->client) - clnt_destroy(kcp->client); - free(kcp); - } + return (-1); } +__sym_compat(key_decryptsession, __key_decryptsession, FBSD_1.0); -static void -key_call_init(void) +static int +__key_gendes(des_block *key) { - - key_call_key_error = thr_keycreate(&key_call_key, key_call_destroy); + return (-1); } +__sym_compat(key_gendes, __key_gendes, FBSD_1.0); -/* - * Keep the handle cached. This call may be made quite often. - */ -static CLIENT * -getkeyserv_handle(int vers) +static int +__key_setnet(struct key_netstarg *arg) { - void *localhandle; - struct netconfig *nconf; - struct netconfig *tpconf; - struct key_call_private *kcp; - struct timeval wait_time; - struct utsname u; - int main_thread; - int fd; - -#define TOTAL_TIMEOUT 30 /* total timeout talking to keyserver */ -#define TOTAL_TRIES 5 /* Number of tries */ - - if ((main_thread = thr_main())) { - kcp = key_call_private_main; - } else { - if (thr_once(&key_call_once, key_call_init) != 0 || - key_call_key_error != 0) - return ((CLIENT *) NULL); - kcp = (struct key_call_private *)thr_getspecific(key_call_key); - } - if (kcp == (struct key_call_private *)NULL) { - kcp = (struct key_call_private *)malloc(sizeof (*kcp)); - if (kcp == (struct key_call_private *)NULL) { - return ((CLIENT *) NULL); - } - if (main_thread) - key_call_private_main = kcp; - else - thr_setspecific(key_call_key, (void *) kcp); - kcp->client = NULL; - } - - /* if pid has changed, destroy client and rebuild */ - if (kcp->client != NULL && kcp->pid != getpid()) { - clnt_destroy(kcp->client); - kcp->client = NULL; - } - - if (kcp->client != NULL) { - /* if uid has changed, build client handle again */ - if (kcp->uid != geteuid()) { - kcp->uid = geteuid(); - auth_destroy(kcp->client->cl_auth); - kcp->client->cl_auth = - authsys_create("", kcp->uid, 0, 0, NULL); - if (kcp->client->cl_auth == NULL) { - clnt_destroy(kcp->client); - kcp->client = NULL; - return ((CLIENT *) NULL); - } - } - /* Change the version number to the new one */ - clnt_control(kcp->client, CLSET_VERS, (void *)&vers); - return (kcp->client); - } - if (!(localhandle = setnetconfig())) { - return ((CLIENT *) NULL); - } - tpconf = NULL; -#if defined(__FreeBSD__) - if (uname(&u) == -1) -#else -#if defined(i386) - if (_nuname(&u) == -1) -#elif defined(sparc) - if (_uname(&u) == -1) -#else -#error Unknown architecture! -#endif -#endif - { - endnetconfig(localhandle); - return ((CLIENT *) NULL); - } - while ((nconf = getnetconfig(localhandle)) != NULL) { - if (strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) { - /* - * We use COTS_ORD here so that the caller can - * find out immediately if the server is dead. - */ - if (nconf->nc_semantics == NC_TPI_COTS_ORD) { - kcp->client = clnt_tp_create(u.nodename, - KEY_PROG, vers, nconf); - if (kcp->client) - break; - } else { - tpconf = nconf; - } - } - } - if ((kcp->client == (CLIENT *) NULL) && (tpconf)) - /* Now, try the CLTS or COTS loopback transport */ - kcp->client = clnt_tp_create(u.nodename, - KEY_PROG, vers, tpconf); - endnetconfig(localhandle); - - if (kcp->client == (CLIENT *) NULL) { - return ((CLIENT *) NULL); - } - kcp->uid = geteuid(); - kcp->pid = getpid(); - kcp->client->cl_auth = authsys_create("", kcp->uid, 0, 0, NULL); - if (kcp->client->cl_auth == NULL) { - clnt_destroy(kcp->client); - kcp->client = NULL; - return ((CLIENT *) NULL); - } - - wait_time.tv_sec = TOTAL_TIMEOUT/TOTAL_TRIES; - wait_time.tv_usec = 0; - (void) clnt_control(kcp->client, CLSET_RETRY_TIMEOUT, - (char *)&wait_time); - if (clnt_control(kcp->client, CLGET_FD, (char *)&fd)) - _fcntl(fd, F_SETFD, 1); /* make it "close on exec" */ - - return (kcp->client); + return (-1); } - -/* returns 0 on failure, 1 on success */ +__sym_compat(key_setnet, __key_setnet, FBSD_1.0); static int -key_call(u_long proc, xdrproc_t xdr_arg, void *arg, xdrproc_t xdr_rslt, - void *rslt) +__key_get_conv(char *pkey, des_block *deskey) { - CLIENT *clnt; - struct timeval wait_time; - - if (proc == KEY_ENCRYPT_PK && __key_encryptsession_pk_LOCAL) { - cryptkeyres *res; - res = (*__key_encryptsession_pk_LOCAL)(geteuid(), arg); - *(cryptkeyres*)rslt = *res; - return (1); - } else if (proc == KEY_DECRYPT_PK && __key_decryptsession_pk_LOCAL) { - cryptkeyres *res; - res = (*__key_decryptsession_pk_LOCAL)(geteuid(), arg); - *(cryptkeyres*)rslt = *res; - return (1); - } else if (proc == KEY_GEN && __key_gendes_LOCAL) { - des_block *res; - res = (*__key_gendes_LOCAL)(geteuid(), 0); - *(des_block*)rslt = *res; - return (1); - } - - if ((proc == KEY_ENCRYPT_PK) || (proc == KEY_DECRYPT_PK) || - (proc == KEY_NET_GET) || (proc == KEY_NET_PUT) || - (proc == KEY_GET_CONV)) - clnt = getkeyserv_handle(2); /* talk to version 2 */ - else - clnt = getkeyserv_handle(1); /* talk to version 1 */ - - if (clnt == NULL) { - return (0); - } - - wait_time.tv_sec = TOTAL_TIMEOUT; - wait_time.tv_usec = 0; - - if (clnt_call(clnt, proc, xdr_arg, arg, xdr_rslt, rslt, - wait_time) == RPC_SUCCESS) { - return (1); - } else { - return (0); - } + return (-1); } +__sym_compat(key_get_conv, __key_get_conv, FBSD_1.0); diff --git a/lib/libc/rpc/publickey.5 b/lib/libc/rpc/publickey.5 deleted file mode 100644 index db95c4617b50..000000000000 --- a/lib/libc/rpc/publickey.5 +++ /dev/null @@ -1,40 +0,0 @@ -.Dd October 19, 1987 -.Dt PUBLICKEY 5 -.Os -.Sh NAME -.Nm publickey -.Nd "public key database" -.Sh SYNOPSIS -.Pa /etc/publickey -.Sh DESCRIPTION -.Pa /etc/publickey -is the public key database used for secure -RPC (Remote Procedure Calls). -Each entry in -the database consists of a network user -name (which may either refer to -a user or a hostname), followed by the user's -public key (in hex -notation), a colon, and then the user's -secret key encrypted with -its login password (also in hex notation). -.Pp -This file is altered either by the user through the -.Xr chkey 1 -command or by the system administrator through the -.Xr newkey 8 -command. -The file -.Pa /etc/publickey -should only contain data on the -.Tn NIS -master machine, where it -is converted into the -.Tn NIS -database -.Pa publickey.byname . -.Sh SEE ALSO -.Xr chkey 1 , -.Xr publickey 3 , -.Xr newkey 8 , -.Xr ypupdated 8 diff --git a/lib/libc/rpc/rpc_secure.3 b/lib/libc/rpc/rpc_secure.3 index ce59bba7115f..ca99b06b556d 100644 --- a/lib/libc/rpc/rpc_secure.3 +++ b/lib/libc/rpc/rpc_secure.3 @@ -1,34 +1,17 @@ .\" -.Dd February 16, 1988 -.Dt RPC 3 +.Dd August 10, 2025 +.Dt RPC_SECURE 3 .Os .Sh NAME .Nm rpc_secure .Nd library routines for secure remote procedure calls .Sh SYNOPSIS .In rpc/rpc.h -.Ft AUTH * -.Fo authdes_create -.Fa "char *name" -.Fa "unsigned window" -.Fa "struct sockaddr *addr" -.Fa "des_block *ckey" -.Fc -.Ft int -.Fn authdes_getucred "struct authdes_cred *adc" "uid_t *uid" "gid_t *gid" "int *grouplen" "gid_t *groups" .Ft int .Fn getnetname "char *name" .Ft int .Fn host2netname "char *name" "const char *host" "const char *domain" .Ft int -.Fn key_decryptsession "const char *remotename" "des_block *deskey" -.Ft int -.Fn key_encryptsession "const char *remotename" "des_block *deskey" -.Ft int -.Fn key_gendes "des_block *deskey" -.Ft int -.Fn key_setsecret "const char *key" -.Ft int .Fn netname2host "char *name" "char *host" "int hostlen" .Ft int .Fn netname2user "char *name" "uid_t *uidp" "gid_t *gidp" "int *gidlenp" "gid_t *gidlist" @@ -38,101 +21,11 @@ These routines are part of the .Tn RPC library. -They implement -.Tn DES -Authentication. See .Xr rpc 3 for further details about .Tn RPC . .Pp -The -.Fn authdes_create -is the first of two routines which interface to the -.Tn RPC -secure authentication system, known as -.Tn DES -authentication. -The second is -.Fn authdes_getucred , -below. -.Pp -Note: the keyserver daemon -.Xr keyserv 8 -must be running for the -.Tn DES -authentication system to work. -.Pp -The -.Fn authdes_create -function, -used on the client side, returns an authentication handle that -will enable the use of the secure authentication system. -The first argument -.Fa name -is the network name, or -.Fa netname , -of the owner of the server process. -This field usually -represents a -.Fa hostname -derived from the utility routine -.Fn host2netname , -but could also represent a user name using -.Fn user2netname . -The second field is window on the validity of -the client credential, given in seconds. -A small -window is more secure than a large one, but choosing -too small of a window will increase the frequency of -resynchronizations because of clock drift. -The third -argument -.Fa addr -is optional. -If it is -.Dv NULL , -then the authentication system will assume -that the local clock is always in sync with the server's -clock, and will not attempt resynchronizations. -If an address -is supplied, however, then the system will use the address -for consulting the remote time service whenever -resynchronization -is required. -This argument is usually the -address of the -.Tn RPC -server itself. -The final argument -.Fa ckey -is also optional. -If it is -.Dv NULL , -then the authentication system will -generate a random -.Tn DES -key to be used for the encryption of credentials. -If it is supplied, however, then it will be used instead. -.Pp -The -.Fn authdes_getucred -function, -the second of the two -.Tn DES -authentication routines, -is used on the server side for converting a -.Tn DES -credential, which is -operating system independent, into a -.Ux -credential. -This routine differs from utility routine -.Fn netname2user -in that -.Fn authdes_getucred -pulls its information from a cache, and does not have to do a -Yellow Pages lookup every time it is called to get its information. .Pp The .Fn getnetname @@ -161,72 +54,6 @@ Inverse of .Fn netname2host . .Pp The -.Fn key_decryptsession -function -is an interface to the keyserver daemon, which is associated -with -.Tn RPC Ns 's -secure authentication system -.Tn ( DES -authentication). -User programs rarely need to call it, or its associated routines -.Fn key_encryptsession , -.Fn key_gendes -and -.Fn key_setsecret . -System commands such as -.Xr login 1 -and the -.Tn RPC -library are the main clients of these four routines. -.Pp -The -.Fn key_decryptsession -function -takes a server netname and a -.Tn DES -key, and decrypts the key by -using the public key of the server and the secret key -associated with the effective uid of the calling process. -It -is the inverse of -.Fn key_encryptsession . -.Pp -The -.Fn key_encryptsession -function -is a keyserver interface routine. -It -takes a server netname and a des key, and encrypts -it using the public key of the server and the secret key -associated with the effective uid of the calling process. -It -is the inverse of -.Fn key_decryptsession . -.Pp -The -.Fn key_gendes -function -is a keyserver interface routine. -It -is used to ask the keyserver for a secure conversation key. -Choosing one -.Qq random -is usually not good enough, -because -the common ways of choosing random numbers, such as using the -current time, are very easy to guess. -.Pp -The -.Fn key_setsecret -function -is a keyserver interface routine. -It is used to set the key for -the effective -.Fa uid -of the calling process. -.Pp -The .Fn netname2host function converts from an operating-system independent netname to a diff --git a/lib/libc/rpc/rpc_soc.3 b/lib/libc/rpc/rpc_soc.3 index 4abd4b14c475..e6fd8a0da6e4 100644 --- a/lib/libc/rpc/rpc_soc.3 +++ b/lib/libc/rpc/rpc_soc.3 @@ -1,6 +1,6 @@ .\" $NetBSD: rpc_soc.3,v 1.2 2000/06/07 13:39:43 simonb Exp $ .\" -.Dd February 16, 1988 +.Dd August 10, 2025 .Dt RPC_SOC 3 .Os .Sh NAME @@ -100,16 +100,6 @@ to perform the requested service, and then sends back a reply. Finally, the procedure call returns to the client. .Pp -Routines that are used for Secure -.Tn RPC ( DES -authentication) are described in -.Xr rpc_secure 3 . -Secure -.Tn RPC -can be used only if -.Tn DES -encryption is available. -.Pp .Bl -tag -width indent -compact .It Xo .Ft void @@ -1701,7 +1691,6 @@ This routine modifies the global variable Service implementors usually do not need this routine. .El .Sh SEE ALSO -.Xr rpc_secure 3 , .Xr xdr 3 .Rs .%T "Remote Procedure Calls: Protocol Specification" diff --git a/lib/libc/rpc/rpc_soc.c b/lib/libc/rpc/rpc_soc.c index c63b89594ce6..e293a2ccf22f 100644 --- a/lib/libc/rpc/rpc_soc.c +++ b/lib/libc/rpc/rpc_soc.c @@ -379,36 +379,13 @@ clnt_broadcast(u_long prog, u_long vers, u_long proc, xdrproc_t xargs, * Create the client des authentication object. Obsoleted by * authdes_seccreate(). */ -AUTH * -authdes_create(char *servername, u_int window, struct sockaddr *syncaddr, +static AUTH * +__authdes_create(char *servername, u_int window, struct sockaddr *syncaddr, des_block *ckey) -/* - * char *servername; // network name of server - * u_int window; // time to live - * struct sockaddr *syncaddr; // optional hostaddr to sync with - * des_block *ckey; // optional conversation key to use - */ { - AUTH *dummy; - AUTH *nauth; - char hostname[NI_MAXHOST]; - - if (syncaddr) { - /* - * Change addr to hostname, because that is the way - * new interface takes it. - */ - if (getnameinfo(syncaddr, syncaddr->sa_len, hostname, - sizeof hostname, NULL, 0, 0) != 0) - goto fallback; - - nauth = authdes_seccreate(servername, window, hostname, ckey); - return (nauth); - } -fallback: - dummy = authdes_seccreate(servername, window, NULL, ckey); - return (dummy); + return (NULL); } +__sym_compat(authdes_create, __authdes_create, FBSD_1.0); /* * Create a client handle for a unix connection. Obsoleted by clnt_vc_create() diff --git a/lib/libc/rpc/svc_auth.c b/lib/libc/rpc/svc_auth.c index eb61171733d6..b8a9a8f33ebb 100644 --- a/lib/libc/rpc/svc_auth.c +++ b/lib/libc/rpc/svc_auth.c @@ -114,11 +114,6 @@ _authenticate(struct svc_req *rqst, struct rpc_msg *msg) case AUTH_SHORT: dummy = _svcauth_short(rqst, msg); return (dummy); -#ifdef DES_BUILTIN - case AUTH_DES: - dummy = _svcauth_des(rqst, msg); - return (dummy); -#endif default: break; } @@ -186,9 +181,6 @@ svc_auth_reg(int cred_flavor, case AUTH_NULL: case AUTH_SYS: case AUTH_SHORT: -#ifdef DES_BUILTIN - case AUTH_DES: -#endif /* already registered */ return (1); diff --git a/lib/libc/rpc/svc_auth_des.c b/lib/libc/rpc/svc_auth_des.c index d4736cc851e8..8fde5512e53f 100644 --- a/lib/libc/rpc/svc_auth_des.c +++ b/lib/libc/rpc/svc_auth_des.c @@ -34,17 +34,8 @@ */ /* - * svcauth_des.c, server-side des authentication - * - * We insure for the service the following: - * (1) The timestamp microseconds do not exceed 1 million. - * (2) The timestamp plus the window is less than the current time. - * (3) The timestamp is not less than the one previously - * seen in the current session. - * - * It is up to the server to determine if the window size is - * too small . - * + * svcauth_des.c, server-side des authentication. + * This functionality was removed in FreeBSD 15.0. */ #include "namespace.h" @@ -65,458 +56,27 @@ #include <rpc/svc_auth.h> #include "libc_private.h" -extern int key_decryptsession_pk(const char *, netobj *, des_block *); - -#define debug(msg) printf("svcauth_des: %s\n", msg) - -#define USEC_PER_SEC ((u_long) 1000000L) -#define BEFORE(t1, t2) timercmp(t1, t2, <) - -/* - * LRU cache of conversation keys and some other useful items. - */ -#define AUTHDES_CACHESZ 64 -struct cache_entry { - des_block key; /* conversation key */ - char *rname; /* client's name */ - u_int window; /* credential lifetime window */ - struct timeval laststamp; /* detect replays of creds */ - char *localcred; /* generic local credential */ -}; -static struct cache_entry *authdes_cache/* [AUTHDES_CACHESZ] */; -static short *authdes_lru/* [AUTHDES_CACHESZ] */; - -static void cache_init(void); /* initialize the cache */ -static short cache_spot(des_block *, char *, struct timeval *); /* find an entry in the cache */ -static void cache_ref(short sid); /* note that sid was ref'd */ - -static void invalidate(char *); /* invalidate entry in cache */ - -/* - * cache statistics - */ -static struct { - u_long ncachehits; /* times cache hit, and is not replay */ - u_long ncachereplays; /* times cache hit, and is replay */ - u_long ncachemisses; /* times cache missed */ -} svcauthdes_stats; - /* * Service side authenticator for AUTH_DES */ -enum auth_stat -_svcauth_des(struct svc_req *rqst, struct rpc_msg *msg) +static enum auth_stat +__svcauth_des(struct svc_req *rqst, struct rpc_msg *msg) { - - long *ixdr; - des_block cryptbuf[2]; - struct authdes_cred *cred; - struct authdes_verf verf; - int status; - struct cache_entry *entry; - short sid = 0; - des_block *sessionkey; - des_block ivec; - u_int window; - struct timeval timestamp; - u_long namelen; - struct area { - struct authdes_cred area_cred; - char area_netname[MAXNETNAMELEN+1]; - } *area; - - if (authdes_cache == NULL) { - cache_init(); - } - - area = (struct area *)rqst->rq_clntcred; - cred = (struct authdes_cred *)&area->area_cred; - - /* - * Get the credential - */ - ixdr = (long *)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_LONG(ixdr); - if (namelen > MAXNETNAMELEN) { - return (AUTH_BADCRED); - } - cred->adc_fullname.name = area->area_netname; - bcopy((char *)ixdr, cred->adc_fullname.name, - (u_int)namelen); - cred->adc_fullname.name[namelen] = 0; - ixdr += (RNDUP(namelen) / BYTES_PER_XDR_UNIT); - cred->adc_fullname.key.key.high = (u_long)*ixdr++; - cred->adc_fullname.key.key.low = (u_long)*ixdr++; - cred->adc_fullname.window = (u_long)*ixdr++; - break; - case ADN_NICKNAME: - cred->adc_nickname = (u_long)*ixdr++; - break; - default: - return (AUTH_BADCRED); - } - - /* - * Get the verifier - */ - ixdr = (long *)msg->rm_call.cb_verf.oa_base; - verf.adv_xtimestamp.key.high = (u_long)*ixdr++; - verf.adv_xtimestamp.key.low = (u_long)*ixdr++; - verf.adv_int_u = (u_long)*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 */ - sid = (short)cred->adc_nickname; - if (sid < 0 || sid >= AUTHDES_CACHESZ) { - debug("bad nickname"); - return (AUTH_BADCRED); /* garbled credential */ - } - 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 = (long *)cryptbuf; - timestamp.tv_sec = IXDR_GET_LONG(ixdr); - timestamp.tv_usec = IXDR_GET_LONG(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; - int winverf; - - if (cred->adc_namekind == ADN_FULLNAME) { - window = IXDR_GET_U_LONG(ixdr); - winverf = IXDR_GET_U_LONG(ixdr); - if (winverf != window - 1) { - debug("window verifier mismatch"); - return (AUTH_BADCRED); /* garbled credential */ - } - sid = cache_spot(sessionkey, cred->adc_fullname.name, - ×tamp); - if (sid < 0) { - debug("replayed credential"); - return (AUTH_REJECTEDCRED); /* replay */ - } - nick = 0; - } else { /* ADN_NICKNAME */ - window = authdes_cache[sid].window; - nick = 1; - } - - if ((u_long)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 */ - } - (void)gettimeofday(¤t, NULL); - 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 = (u_long)sid; - - /* - * xdr the timestamp before encrypting - */ - ixdr = (long *)cryptbuf; - IXDR_PUT_LONG(ixdr, timestamp.tv_sec - 1); - IXDR_PUT_LONG(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 = (long *)msg->rm_call.cb_verf.oa_base; - *ixdr++ = (long)verf.adv_xtimestamp.key.high; - *ixdr++ = (long)verf.adv_xtimestamp.key.low; - *ixdr++ = (long)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) { - cred->adc_fullname.window = window; - cred->adc_nickname = (u_long)sid; /* save nickname */ - if (entry->rname != NULL) { - mem_free(entry->rname, strlen(entry->rname) + 1); - } - entry->rname = (char *)mem_alloc((u_int)strlen(cred->adc_fullname.name) - + 1); - if (entry->rname != NULL) { - (void) strcpy(entry->rname, cred->adc_fullname.name); - } else { - debug("out of memory"); - } - 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!*/ + return (AUTH_FAILED); } +__sym_compat(_svcauth_des, __svcauth_des, FBSD_1.0); /* - * Initialize the cache - */ -static void -cache_init(void) -{ - int i; - - authdes_cache = (struct cache_entry *) - mem_alloc(sizeof(struct cache_entry) * AUTHDES_CACHESZ); - bzero((char *)authdes_cache, - sizeof(struct cache_entry) * AUTHDES_CACHESZ); - - authdes_lru = (short *)mem_alloc(sizeof(short) * 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(short sid) -{ - int i; - short curr; - short 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(des_block *key, char *name, struct timeval *timestamp) -{ - struct cache_entry *cp; - int i; - u_long 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 && - bcmp(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 */ -} - - -#if (defined(sun) || defined(vax) || defined(__FreeBSD__)) -/* - * Local credential handling stuff. - * NOTE: bsd unix dependent. - * Other operating systems should put something else here. - */ -#define UNKNOWN -2 /* grouplen, if cached cred is unknown user */ -#define INVALID -1 /* grouplen, if cache entry is invalid */ - -struct bsdcred { - uid_t uid; /* cached uid */ - gid_t gid; /* cached gid */ - int grouplen; /* length of cached groups */ - gid_t groups[NGRPS]; /* cached groups */ -}; - -/* * Map a des credential into a unix cred. * We cache the credential here so the application does * not have to make an rpc call every time to interpret * the credential. */ -int -authdes_getucred(struct authdes_cred *adc, uid_t *uid, gid_t *gid, +static int +__authdes_getucred(void *adc, uid_t *uid, gid_t *gid, int *grouplen, gid_t *groups) { - unsigned sid; - int i; - uid_t i_uid; - gid_t i_gid; - int i_grouplen; - struct bsdcred *cred; - - sid = adc->adc_nickname; - if (sid >= AUTHDES_CACHESZ) { - debug("invalid nickname"); - return (0); - } - cred = (struct bsdcred *)authdes_cache[sid].localcred; - if (cred == NULL) { - cred = (struct bsdcred *)mem_alloc(sizeof(struct bsdcred)); - authdes_cache[sid].localcred = (char *)cred; - cred->grouplen = INVALID; - } - if (cred->grouplen == INVALID) { - /* - * not in cache: lookup - */ - if (!netname2user(adc->adc_fullname.name, &i_uid, &i_gid, - &i_grouplen, groups)) - { - debug("unknown netname"); - cred->grouplen = UNKNOWN; /* mark as lookup up, but not found */ - return (0); - } - debug("missed ucred cache"); - *uid = cred->uid = i_uid; - *gid = cred->gid = i_gid; - *grouplen = cred->grouplen = i_grouplen; - for (i = i_grouplen - 1; i >= 0; i--) { - cred->groups[i] = groups[i]; /* int to short */ - } - return (1); - } else if (cred->grouplen == UNKNOWN) { - /* - * Already lookup up, but no match found - */ - return (0); - } - - /* - * cached credentials - */ - *uid = cred->uid; - *gid = cred->gid; - *grouplen = cred->grouplen; - for (i = cred->grouplen - 1; i >= 0; i--) { - groups[i] = cred->groups[i]; /* short to int */ - } - return (1); -} - -static void -invalidate(char *cred) -{ - if (cred == NULL) { - return; - } - ((struct bsdcred *)cred)->grouplen = INVALID; + return (0); } -#endif - +__sym_compat(authdes_getucred, __authdes_getucred, FBSD_1.0); diff --git a/lib/libc/stdlib/qsort.c b/lib/libc/stdlib/qsort.c index e0b06494cf98..400124593d07 100644 --- a/lib/libc/stdlib/qsort.c +++ b/lib/libc/stdlib/qsort.c @@ -106,13 +106,11 @@ local_qsort(void *a, size_t n, size_t es, cmp_t *cmp, void *thunk) char *pa, *pb, *pc, *pd, *pl, *pm, *pn; size_t d1, d2; int cmp_result; - int swap_cnt; /* if there are less than 2 elements, then sorting is not needed */ if (__predict_false(n < 2)) return; loop: - swap_cnt = 0; if (n < 7) { for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) for (pl = pm; @@ -141,7 +139,6 @@ loop: for (;;) { while (pb <= pc && (cmp_result = CMP(thunk, pb, a)) <= 0) { if (cmp_result == 0) { - swap_cnt = 1; swapfunc(pa, pb, es); pa += es; } @@ -149,7 +146,6 @@ loop: } while (pb <= pc && (cmp_result = CMP(thunk, pc, a)) >= 0) { if (cmp_result == 0) { - swap_cnt = 1; swapfunc(pc, pd, es); pd -= es; } @@ -158,18 +154,9 @@ loop: if (pb > pc) break; swapfunc(pb, pc, es); - swap_cnt = 1; pb += es; pc -= es; } - if (swap_cnt == 0) { /* Switch to insertion sort */ - for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) - for (pl = pm; - pl > (char *)a && CMP(thunk, pl - es, pl) > 0; - pl -= es) - swapfunc(pl, pl - es, es); - return; - } pn = (char *)a + n * es; d1 = MIN(pa - (char *)a, pb - pa); diff --git a/lib/libc/tests/stdlib/Makefile b/lib/libc/tests/stdlib/Makefile index 50726a5d8af6..9d84becfbd1f 100644 --- a/lib/libc/tests/stdlib/Makefile +++ b/lib/libc/tests/stdlib/Makefile @@ -14,6 +14,7 @@ ATF_TESTS_C+= qsort_b_test ATF_TESTS_C+= qsort_r_compat_test ATF_TESTS_C+= qsort_r_test ATF_TESTS_C+= qsort_s_test +ATF_TESTS_C+= qsort_bench ATF_TESTS_C+= set_constraint_handler_s_test ATF_TESTS_C+= strfmon_test ATF_TESTS_C+= tsearch_test diff --git a/lib/libc/tests/stdlib/qsort_bench.c b/lib/libc/tests/stdlib/qsort_bench.c new file mode 100644 index 000000000000..5f2cfae40140 --- /dev/null +++ b/lib/libc/tests/stdlib/qsort_bench.c @@ -0,0 +1,113 @@ +/*- + * Copyright (c) 2025 Dag-Erling Smørgrav <des@FreeBSD.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <atf-c.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> + +/*- + * Measures qsort(3) runtime with pathological input and verify that it + * stays close to N * log2(N). + * + * Thanks to Vivian Hussey for the proof of concept. + * + * The input we construct is similar to a sweep from 0 to N where each + * half, except for the first element, has been reversed; for instance, + * with N = 8, we get { 0, 3, 2, 1, 4, 8, 7, 6 }. This triggers a bug in + * the BSD qsort(3) where it will switch to insertion sort if the pivots + * are sorted. + * + * This article goes into more detail about the bug and its origin: + * + * https://www.raygard.net/2022/02/26/Re-engineering-a-qsort-part-3 + * + * With this optimization (the `if (swap_cnt == 0)` block), qsort(3) needs + * roughly N * N / 4 comparisons to sort our pathological input. Without + * it, it needs only a little more than N * log2(N) comparisons. + */ + +/* we stop testing once a single takes longer than this */ +#define MAXRUNSECS 10 + +static bool debugging; + +static uintmax_t ncmp; + +static int +intcmp(const void *a, const void *b) +{ + ncmp++; + return ((*(int *)a > *(int *)b) - (*(int *)a < *(int *)b)); +} + +static void +qsort_bench(int log2n) +{ + uintmax_t n = 1LLU << log2n; + int *buf; + + /* fill an array with a pathological pattern */ + ATF_REQUIRE(buf = malloc(n * sizeof(*buf))); + buf[0] = 0; + buf[n / 2] = n / 2; + for (unsigned int i = 1; i < n / 2; i++) { + buf[i] = n / 2 - i; + buf[n / 2 + i] = n - i; + } + + ncmp = 0; + qsort(buf, n, sizeof(*buf), intcmp); + + /* check result and free array */ + if (debugging) { + for (unsigned int i = 1; i < n; i++) { + ATF_REQUIRE_MSG(buf[i] > buf[i - 1], + "array is not sorted"); + } + } + free(buf); + + /* check that runtime does not exceed N² */ + ATF_CHECK_MSG(ncmp / n < n, + "runtime %ju exceeds N² for N = %ju", ncmp, n); + + /* check that runtime does not exceed N log N by much */ + ATF_CHECK_MSG(ncmp / n <= log2n + 1, + "runtime %ju exceeds N log N for N = %ju", ncmp, n); +} + +ATF_TC_WITHOUT_HEAD(qsort_bench); +ATF_TC_BODY(qsort_bench, tc) +{ + struct timespec t0, t1; + uintmax_t tus; + + for (int i = 10; i <= 30; i++) { + clock_gettime(CLOCK_UPTIME, &t0); + qsort_bench(i); + clock_gettime(CLOCK_UPTIME, &t1); + tus = t1.tv_sec * 1000000 + t1.tv_nsec / 1000; + tus -= t0.tv_sec * 1000000 + t0.tv_nsec / 1000; + if (debugging) { + fprintf(stderr, "N = 2^%d in %ju.%06jus\n", + i, tus / 1000000, tus % 1000000); + } + /* stop once an individual run exceeds our limit */ + if (tus / 1000000 >= MAXRUNSECS) + break; + } +} + +ATF_TP_ADD_TCS(tp) +{ + debugging = !getenv("__RUNNING_INSIDE_ATF_RUN") && + isatty(STDERR_FILENO); + ATF_TP_ADD_TC(tp, qsort_bench); + return (atf_no_error()); +} diff --git a/lib/librpcsvc/Makefile b/lib/librpcsvc/Makefile index bdd01c91adab..04e57990a29d 100644 --- a/lib/librpcsvc/Makefile +++ b/lib/librpcsvc/Makefile @@ -14,7 +14,7 @@ OTHERSRCS= rnusers.c rstat.c rwall.c SECRPCSRCS= secretkey.c xcrypt.c .if ${MK_NIS} != "no" -OTHERSRCS+= yp_passwd.c yp_update.c +OTHERSRCS+= yp_passwd.c .endif RPCCOM= RPCGEN_CPP=${CPP:Q} rpcgen -C diff --git a/lib/librpcsvc/yp_update.c b/lib/librpcsvc/yp_update.c deleted file mode 100644 index 8a31b2c22d9b..000000000000 --- a/lib/librpcsvc/yp_update.c +++ /dev/null @@ -1,199 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 1995, 1996 - * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * ypupdate client-side library function. - * - * Written by Bill Paul <wpaul@ctr.columbia.edu> - * Center for Telecommunications Research - * Columbia University, New York City - */ - -#include <sys/cdefs.h> -#include <stdlib.h> -#include <rpc/rpc.h> -#include <rpcsvc/yp_prot.h> -#include <rpcsvc/ypclnt.h> -#include <rpcsvc/ypupdate_prot.h> -#include <rpc/key_prot.h> - -#ifndef WINDOW -#define WINDOW (60*60) -#endif - -#ifndef TIMEOUT -#define TIMEOUT 300 -#endif - -int -yp_update(char *domain, char *map, unsigned int ypop, char *key, int keylen, - char *data, int datalen) -{ - char *master; - int rval; - unsigned int res; - struct ypupdate_args upargs; - struct ypdelete_args delargs; - CLIENT *clnt; - char netname[MAXNETNAMELEN+1]; - des_block des_key; - struct timeval timeout; - - /* Get the master server name for 'domain.' */ - if ((rval = yp_master(domain, map, &master))) - return(rval); - - /* Check that ypupdated is running there. */ - if (getrpcport(master, YPU_PROG, YPU_VERS, ypop)) - return(YPERR_DOMAIN); - - /* Get a handle. */ - if ((clnt = clnt_create(master, YPU_PROG, YPU_VERS, "tcp")) == NULL) - return(YPERR_RPC); - - /* - * Assemble netname of server. - * NOTE: It's difficult to discern from the documentation, but - * when you make a Secure RPC call, the netname you pass should - * be the netname of the guy on the other side, not your own - * netname. This is how the client side knows what public key - * to use for the initial exchange. Passing your own netname - * only works if the server on the other side is running under - * your UID. - */ - if (!host2netname(netname, master, domain)) { - clnt_destroy(clnt); - return(YPERR_BADARGS); - } - - /* Make up a DES session key. */ - key_gendes(&des_key); - - /* Set up DES authentication. */ - if ((clnt->cl_auth = (AUTH *)authdes_create(netname, WINDOW, NULL, - &des_key)) == NULL) { - clnt_destroy(clnt); - return(YPERR_RESRC); - } - - /* Set a timeout for clnt_call(). */ - timeout.tv_usec = 0; - timeout.tv_sec = TIMEOUT; - - /* - * Make the call. Note that we use clnt_call() here rather than - * the rpcgen-erated client stubs. We could use those stubs, but - * then we'd have to do some gymnastics to get at the error - * information to figure out what error code to send back to the - * caller. With clnt_call(), we get the error status returned to - * us right away, and we only have to exert a small amount of - * extra effort. - */ - switch (ypop) { - case YPOP_CHANGE: - upargs.mapname = map; - upargs.key.yp_buf_len = keylen; - upargs.key.yp_buf_val = key; - upargs.datum.yp_buf_len = datalen; - upargs.datum.yp_buf_val = data; - - if ((rval = clnt_call(clnt, YPU_CHANGE, - (xdrproc_t)xdr_ypupdate_args, &upargs, - (xdrproc_t)xdr_u_int, &res, timeout)) != RPC_SUCCESS) { - if (rval == RPC_AUTHERROR) - res = YPERR_ACCESS; - else - res = YPERR_RPC; - } - - break; - case YPOP_INSERT: - upargs.mapname = map; - upargs.key.yp_buf_len = keylen; - upargs.key.yp_buf_val = key; - upargs.datum.yp_buf_len = datalen; - upargs.datum.yp_buf_val = data; - - if ((rval = clnt_call(clnt, YPU_INSERT, - (xdrproc_t)xdr_ypupdate_args, &upargs, - (xdrproc_t)xdr_u_int, &res, timeout)) != RPC_SUCCESS) { - if (rval == RPC_AUTHERROR) - res = YPERR_ACCESS; - else - res = YPERR_RPC; - } - - break; - case YPOP_DELETE: - delargs.mapname = map; - delargs.key.yp_buf_len = keylen; - delargs.key.yp_buf_val = key; - - if ((rval = clnt_call(clnt, YPU_DELETE, - (xdrproc_t)xdr_ypdelete_args, &delargs, - (xdrproc_t)xdr_u_int, &res, timeout)) != RPC_SUCCESS) { - if (rval == RPC_AUTHERROR) - res = YPERR_ACCESS; - else - res = YPERR_RPC; - } - - break; - case YPOP_STORE: - upargs.mapname = map; - upargs.key.yp_buf_len = keylen; - upargs.key.yp_buf_val = key; - upargs.datum.yp_buf_len = datalen; - upargs.datum.yp_buf_val = data; - - if ((rval = clnt_call(clnt, YPU_STORE, - (xdrproc_t)xdr_ypupdate_args, &upargs, - (xdrproc_t)xdr_u_int, &res, timeout)) != RPC_SUCCESS) { - if (rval == RPC_AUTHERROR) - res = YPERR_ACCESS; - else - res = YPERR_RPC; - } - - break; - default: - res = YPERR_BADARGS; - break; - } - - /* All done: tear down the connection. */ - auth_destroy(clnt->cl_auth); - clnt_destroy(clnt); - free(master); - - return(res); -} diff --git a/lib/libsys/Symbol.sys.map b/lib/libsys/Symbol.sys.map index 45e0160100af..1a297f9df581 100644 --- a/lib/libsys/Symbol.sys.map +++ b/lib/libsys/Symbol.sys.map @@ -89,7 +89,6 @@ FBSD_1.0 { geteuid; getfh; getgid; - getgroups; getitimer; getpagesize; getpeername; @@ -204,7 +203,6 @@ FBSD_1.0 { setegid; seteuid; setgid; - setgroups; setitimer; setlogin; setpgid; @@ -380,11 +378,13 @@ FBSD_1.7 { FBSD_1.8 { exterrctl; fchroot; + getgroups; getrlimitusage; inotify_add_watch_at; inotify_rm_watch; kcmp; setcred; + setgroups; }; FBSDprivate_1.0 { diff --git a/lib/libsys/_libsys.h b/lib/libsys/_libsys.h index 2f89e8fea92b..34eebc1aa67a 100644 --- a/lib/libsys/_libsys.h +++ b/lib/libsys/_libsys.h @@ -121,8 +121,6 @@ typedef int (__sys_munmap_t)(void *, size_t); typedef int (__sys_mprotect_t)(void *, size_t, int); typedef int (__sys_madvise_t)(void *, size_t, int); typedef int (__sys_mincore_t)(const void *, size_t, char *); -typedef int (__sys_getgroups_t)(int, gid_t *); -typedef int (__sys_setgroups_t)(int, const gid_t *); typedef int (__sys_getpgrp_t)(void); typedef int (__sys_setpgid_t)(int, int); typedef int (__sys_setitimer_t)(int, const struct itimerval *, struct itimerval *); @@ -468,6 +466,8 @@ typedef int (__sys_setcred_t)(u_int, const struct setcred *, size_t); typedef int (__sys_exterrctl_t)(u_int, u_int, void *); typedef int (__sys_inotify_add_watch_at_t)(int, int, const char *, uint32_t); typedef int (__sys_inotify_rm_watch_t)(int, int); +typedef int (__sys_getgroups_t)(int, gid_t *); +typedef int (__sys_setgroups_t)(int, const gid_t *); _Noreturn void __sys__exit(int rval); int __sys_fork(void); @@ -525,8 +525,6 @@ int __sys_munmap(void * addr, size_t len); int __sys_mprotect(void * addr, size_t len, int prot); int __sys_madvise(void * addr, size_t len, int behav); int __sys_mincore(const void * addr, size_t len, char * vec); -int __sys_getgroups(int gidsetsize, gid_t * gidset); -int __sys_setgroups(int gidsetsize, const gid_t * gidset); int __sys_getpgrp(void); int __sys_setpgid(int pid, int pgid); int __sys_setitimer(int which, const struct itimerval * itv, struct itimerval * oitv); @@ -872,6 +870,8 @@ int __sys_setcred(u_int flags, const struct setcred * wcred, size_t size); int __sys_exterrctl(u_int op, u_int flags, void * ptr); int __sys_inotify_add_watch_at(int fd, int dfd, const char * path, uint32_t mask); int __sys_inotify_rm_watch(int fd, int wd); +int __sys_getgroups(int gidsetsize, gid_t * gidset); +int __sys_setgroups(int gidsetsize, const gid_t * gidset); __END_DECLS #endif /* __LIBSYS_H_ */ diff --git a/lib/libsys/getgroups.2 b/lib/libsys/getgroups.2 index 91cca2748ec2..37c8fbad7215 100644 --- a/lib/libsys/getgroups.2 +++ b/lib/libsys/getgroups.2 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd January 21, 2011 +.Dd August 1, 2025 .Dt GETGROUPS 2 .Os .Sh NAME @@ -41,8 +41,8 @@ The .Fn getgroups system call -gets the current group access list of the user process -and stores it in the array +gets the current supplementary groups of the user process and stores it in the +array .Fa gidset . The .Fa gidsetlen @@ -54,7 +54,7 @@ The system call returns the actual number of groups returned in .Fa gidset . -At least one and as many as {NGROUPS_MAX}+1 values may be returned. +As many as {NGROUPS_MAX} values may be returned. If .Fa gidsetlen is zero, @@ -102,3 +102,10 @@ The .Fn getgroups system call appeared in .Bx 4.2 . +.Pp +Before +.Fx 15.0 , +the +.Fn getgroups +system call always returned the effective group ID for the process as the first +element of the array, before the supplementary groups. diff --git a/lib/libsys/pathconf.2 b/lib/libsys/pathconf.2 index 79ac8310000d..5a983a3a13e2 100644 --- a/lib/libsys/pathconf.2 +++ b/lib/libsys/pathconf.2 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd July 5, 2025 +.Dd August 6, 2025 .Dt PATHCONF 2 .Os .Sh NAME @@ -187,6 +187,11 @@ and flags can be set by .Xr chflags 2 , otherwise 0. +.It Li _PC_CLONE_BLKSIZE +Returns the block size required for block cloning via +.Xr copy_file_range 2 +for a file system if block cloning is supported, +otherwise 0. .El .Sh RETURN VALUES If the call to @@ -264,6 +269,7 @@ Corrupted data was detected while reading from the file system. .El .Sh SEE ALSO .Xr chflags 2 , +.Xr copy_file_range 2 , .Xr lseek 2 , .Xr sysctl 3 .Sh HISTORY diff --git a/lib/libsys/setgroups.2 b/lib/libsys/setgroups.2 index a226aeafea96..451f63ba1266 100644 --- a/lib/libsys/setgroups.2 +++ b/lib/libsys/setgroups.2 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd January 19, 2018 +.Dd August 1, 2025 .Dt SETGROUPS 2 .Os .Sh NAME @@ -42,7 +42,7 @@ The .Fn setgroups system call -sets the group access list of the current user process +sets the supplementary group list of the current user process according to the array .Fa gidset . The @@ -50,26 +50,12 @@ The argument indicates the number of entries in the array and must be no more than -.Dv {NGROUPS_MAX}+1 . -.Pp -Only the super-user may set a new group list. +.Dv {NGROUPS_MAX} . +The +.Fa ngroups +argument may be set to 0 to clear the supplementary group list. .Pp -The first entry of the group array -.Pq Va gidset[0] -is used as the effective group-ID for the process. -This entry is over-written when a setgid program is run. -To avoid losing access to the privileges of the -.Va gidset[0] -entry, it should be duplicated later in the group array. -By convention, -this happens because the group value indicated -in the password file also appears in -.Pa /etc/group . -The group value in the password file is placed in -.Va gidset[0] -and that value then gets added a second time when the -.Pa /etc/group -file is scanned to create the group set. +Only the super-user may set a new supplementary group list. .Sh RETURN VALUES .Rv -std setgroups .Sh ERRORS @@ -99,3 +85,11 @@ The .Fn setgroups system call appeared in .Bx 4.2 . +.Pp +Before +.Fx 15.0 , +the +.Fn setgroups +system call would set the effective group ID for the process to the first +element of +.Fa gidset . diff --git a/lib/libsys/shm_open.2 b/lib/libsys/shm_open.2 index 8bea939690ba..c3196d966e6b 100644 --- a/lib/libsys/shm_open.2 +++ b/lib/libsys/shm_open.2 @@ -26,7 +26,7 @@ .\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd January 30, 2023 +.Dd August 4, 2025 .Dt SHM_OPEN 2 .Os .Sh NAME @@ -74,8 +74,9 @@ must be included in The optional flags .Dv O_CREAT , .Dv O_EXCL , +.Dv O_TRUNC , and -.Dv O_TRUNC +.Dv O_CLOFORK may also be specified. .Pp If diff --git a/lib/libsys/syscalls.map b/lib/libsys/syscalls.map index dbb011343c8f..4cf80a2ffc69 100644 --- a/lib/libsys/syscalls.map +++ b/lib/libsys/syscalls.map @@ -117,10 +117,6 @@ FBSDprivate_1.0 { __sys_madvise; _mincore; __sys_mincore; - _getgroups; - __sys_getgroups; - _setgroups; - __sys_setgroups; _getpgrp; __sys_getpgrp; _setpgid; @@ -813,4 +809,8 @@ FBSDprivate_1.0 { __sys_inotify_add_watch_at; _inotify_rm_watch; __sys_inotify_rm_watch; + _getgroups; + __sys_getgroups; + _setgroups; + __sys_setgroups; }; diff --git a/lib/libutil++/Makefile b/lib/libutil++/Makefile index 729a336ddb3a..56b64bbf358c 100644 --- a/lib/libutil++/Makefile +++ b/lib/libutil++/Makefile @@ -1,4 +1,3 @@ -PACKAGE= clibs LIB_CXX= util++ INTERNALLIB= true SHLIB_MAJOR= 1 diff --git a/lib/libutil/Makefile b/lib/libutil/Makefile index f8c566ca731a..f6251c093345 100644 --- a/lib/libutil/Makefile +++ b/lib/libutil/Makefile @@ -136,7 +136,6 @@ MLINKS+=quotafile.3 quota_on.3 MLINKS+=quotafile.3 quota_open.3 MLINKS+=quotafile.3 quota_qfname.3 MLINKS+=quotafile.3 quota_read.3 -MLINKS+=quotafile.3 quota_statfs.3 MLINKS+=quotafile.3 quota_write_limits.3 MLINKS+=quotafile.3 quota_write_usage.3 MAN+= realhostname.3 diff --git a/lib/libutil/login.conf.5 b/lib/libutil/login.conf.5 index d43fdfb761f3..27f37fb5fc30 100644 --- a/lib/libutil/login.conf.5 +++ b/lib/libutil/login.conf.5 @@ -380,14 +380,15 @@ If is specified, then logins are only allowed during the periods given. If .Em times.deny -is specified, then logins are denied during the periods given, regardless of whether -one of the periods specified in +is specified, then logins are denied during the periods given, +regardless of whether one of the periods specified in .Em times.allow applies. .Pp Note that .Xr login 1 -enforces only that the actual login falls within periods allowed by these entries. +enforces only that the actual login falls within periods allowed by +these entries. Further enforcement over the life of a session requires a separate daemon to monitor transitions from an allowed period to a non-allowed one. .Pp diff --git a/lib/libutil/login_auth.3 b/lib/libutil/login_auth.3 index fafe43b906e6..dd5ba3e01265 100644 --- a/lib/libutil/login_auth.3 +++ b/lib/libutil/login_auth.3 @@ -58,8 +58,8 @@ .\" .Ft int .\" .Fn auth_timesok "login_cap_t *lc" "time_t now" .Sh DESCRIPTION -This set of functions support the login class authorisation style interface provided -by +This set of functions support the login class authorisation style +interface provided by .Xr login.conf 5 . .\" .Sh RETURN VALUES .Sh SEE ALSO diff --git a/lib/libutil/login_cap.3 b/lib/libutil/login_cap.3 index 86142c3b19f9..48af0e3c9c46 100644 --- a/lib/libutil/login_cap.3 +++ b/lib/libutil/login_cap.3 @@ -31,6 +31,7 @@ .Nm login_getcaptime , .Nm login_getclass , .Nm login_getclassbyname , +.Nm login_getpath , .Nm login_getpwclass , .Nm login_getstyle , .Nm login_getuserclass , diff --git a/lib/libutil/mntopts.3 b/lib/libutil/mntopts.3 index 35f6d476fcec..28e5a02442c2 100644 --- a/lib/libutil/mntopts.3 +++ b/lib/libutil/mntopts.3 @@ -342,9 +342,9 @@ By default .Va getmnt_silent is zero. .Sh SEE ALSO +.Xr nmount 2 , .Xr err 3 , -.Xr mount 8 , -.Xr nmount 8 +.Xr mount 8 .Sh HISTORY The .Fn getmntopts @@ -358,7 +358,7 @@ The and .Fn rmslashes functions were added with -.Xr nmount 8 +.Xr nmount 2 in .Fx 5.0 . The @@ -368,7 +368,9 @@ and functions were added in .Fx 13.2 . .Pp -Historically, these functions were found in getmntopts.c in the sources for the +Historically, these functions were found in +.Pa getmntopts.c +in the source code of the .Xr mount 8 program. As of diff --git a/lib/libutil/uucplock.3 b/lib/libutil/uucplock.3 index dd19d0311b4e..ee8c9f6bb995 100644 --- a/lib/libutil/uucplock.3 +++ b/lib/libutil/uucplock.3 @@ -28,6 +28,7 @@ .Os .Sh NAME .Nm uu_lock , +.Nm uu_lock_txfr , .Nm uu_unlock , .Nm uu_lockerr .Nd acquire and release control of a serial device diff --git a/lib/msun/src/e_fmod.c b/lib/msun/src/e_fmod.c index 77afd116c658..ced9cce33aa0 100644 --- a/lib/msun/src/e_fmod.c +++ b/lib/msun/src/e_fmod.c @@ -26,14 +26,14 @@ static const double one = 1.0, Zero[] = {0.0, -0.0,}; double fmod(double x, double y) { - int32_t n,hx,hy,hz,ix,iy,sx,i; - u_int32_t lx,ly,lz; + int32_t hx, hy, hz, ix, iy, n, sx; + u_int32_t lx, ly, lz; EXTRACT_WORDS(hx,lx,x); EXTRACT_WORDS(hy,ly,y); sx = hx&0x80000000; /* sign of x */ - hx ^=sx; /* |x| */ - hy &= 0x7fffffff; /* |y| */ + hx ^= sx; /* |x| */ + hy &= 0x7fffffff; /* |y| */ /* purge off exception values */ if((hy|ly)==0||(hx>=0x7ff00000)|| /* y=0,or x not finite */ @@ -46,22 +46,16 @@ fmod(double x, double y) } /* determine ix = ilogb(x) */ - if(hx<0x00100000) { /* subnormal x */ - if(hx==0) { - for (ix = -1043, i=lx; i>0; i<<=1) ix -=1; - } else { - for (ix = -1022,i=(hx<<11); i>0; i<<=1) ix -=1; - } - } else ix = (hx>>20)-1023; + if(hx<0x00100000) + ix = subnormal_ilogb(hx, lx); + else + ix = (hx>>20)-1023; /* determine iy = ilogb(y) */ - if(hy<0x00100000) { /* subnormal y */ - if(hy==0) { - for (iy = -1043, i=ly; i>0; i<<=1) iy -=1; - } else { - for (iy = -1022,i=(hy<<11); i>0; i<<=1) iy -=1; - } - } else iy = (hy>>20)-1023; + if(hy<0x00100000) + iy = subnormal_ilogb(hy, ly); + else + iy = (hy>>20)-1023; /* set up {hx,lx}, {hy,ly} and align y to x */ if(ix >= -1022) diff --git a/lib/msun/src/e_fmodf.c b/lib/msun/src/e_fmodf.c index a7d1a0c22acd..ada969db44c7 100644 --- a/lib/msun/src/e_fmodf.c +++ b/lib/msun/src/e_fmodf.c @@ -27,7 +27,7 @@ static const float one = 1.0, Zero[] = {0.0, -0.0,}; float fmodf(float x, float y) { - int32_t n,hx,hy,hz,ix,iy,sx,i; + int32_t hx, hy, hz, ix, iy, n, sx; GET_FLOAT_WORD(hx,x); GET_FLOAT_WORD(hy,y); @@ -44,14 +44,16 @@ fmodf(float x, float y) return Zero[(u_int32_t)sx>>31]; /* |x|=|y| return x*0*/ /* determine ix = ilogb(x) */ - if(hx<0x00800000) { /* subnormal x */ - for (ix = -126,i=(hx<<8); i>0; i<<=1) ix -=1; - } else ix = (hx>>23)-127; + if(hx<0x00800000) + ix = subnormal_ilogbf(hx); + else + ix = (hx>>23)-127; /* determine iy = ilogb(y) */ - if(hy<0x00800000) { /* subnormal y */ - for (iy = -126,i=(hy<<8); i>=0; i<<=1) iy -=1; - } else iy = (hy>>23)-127; + if(hy<0x00800000) + iy = subnormal_ilogbf(hy); + else + iy = (hy>>23)-127; /* set up {hx,lx}, {hy,ly} and align y to x */ if(ix >= -126) diff --git a/lib/msun/src/math_private.h b/lib/msun/src/math_private.h index 1595f902846c..fbd84e246ca7 100644 --- a/lib/msun/src/math_private.h +++ b/lib/msun/src/math_private.h @@ -739,6 +739,41 @@ irintl(long double x) (ar) = (x) - (ai); \ } while (0) +/* + * For a subnormal double entity split into high and low parts, compute ilogb. + */ +static inline int32_t +subnormal_ilogb(int32_t hi, int32_t lo) +{ + int32_t j; + uint32_t i; + + j = -1022; + if (hi == 0) { + j -= 21; + i = (uint32_t)lo; + } else + i = (uint32_t)hi << 11; + + for (; i < 0x7fffffff; i <<= 1) j -= 1; + + return (j); +} + +/* + * For a subnormal float entity represented as an int32_t, compute ilogb. + */ +static inline int32_t +subnormal_ilogbf(int32_t hx) +{ + int32_t j; + uint32_t i; + i = (uint32_t) hx << 8; + for (j = -126; i < 0x7fffffff; i <<= 1) j -=1; + + return (j); +} + #ifdef DEBUG #if defined(__amd64__) || defined(__i386__) #define breakpoint() asm("int $3") diff --git a/lib/msun/src/s_ilogb.c b/lib/msun/src/s_ilogb.c index 27e0bbb8735b..aa707d51d7b7 100644 --- a/lib/msun/src/s_ilogb.c +++ b/lib/msun/src/s_ilogb.c @@ -21,21 +21,18 @@ #include "math.h" #include "math_private.h" - int ilogb(double x) +int +ilogb(double x) { - int32_t hx,lx,ix; + int32_t hx, ix, lx; EXTRACT_WORDS(hx,lx,x); hx &= 0x7fffffff; if(hx<0x00100000) { if((hx|lx)==0) return FP_ILOGB0; - else /* subnormal x */ - if(hx==0) { - for (ix = -1043; lx>0; lx<<=1) ix -=1; - } else { - for (ix = -1022,hx<<=11; hx>0; hx<<=1) ix -=1; - } + else + ix = subnormal_ilogb(hx, lx); return ix; } else if (hx<0x7ff00000) return (hx>>20)-1023; diff --git a/lib/msun/src/s_ilogbf.c b/lib/msun/src/s_ilogbf.c index e0f8fee26ac8..5195e2331af3 100644 --- a/lib/msun/src/s_ilogbf.c +++ b/lib/msun/src/s_ilogbf.c @@ -18,7 +18,8 @@ #include "math.h" #include "math_private.h" - int ilogbf(float x) +int +ilogbf(float x) { int32_t hx,ix; @@ -28,7 +29,7 @@ if(hx==0) return FP_ILOGB0; else /* subnormal x */ - for (ix = -126,hx<<=8; hx>0; hx<<=1) ix -=1; + ix = subnormal_ilogbf(hx); return ix; } else if (hx<0x7f800000) return (hx>>23)-127; diff --git a/lib/msun/src/s_remquo.c b/lib/msun/src/s_remquo.c index 206d2903cd86..b26b5619f3ad 100644 --- a/lib/msun/src/s_remquo.c +++ b/lib/msun/src/s_remquo.c @@ -4,7 +4,7 @@ * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice + * software is freely granted, provided that this notice * is preserved. * ==================================================== */ @@ -27,7 +27,7 @@ static const double Zero[] = {0.0, -0.0,}; double remquo(double x, double y, int *quo) { - int32_t n,hx,hy,hz,ix,iy,sx,i; + int32_t hx,hy,hz,ix,iy,n,sx; u_int32_t lx,ly,lz,q,sxy; EXTRACT_WORDS(hx,lx,x); @@ -53,25 +53,19 @@ remquo(double x, double y, int *quo) } /* determine ix = ilogb(x) */ - if(hx<0x00100000) { /* subnormal x */ - if(hx==0) { - for (ix = -1043, i=lx; i>0; i<<=1) ix -=1; - } else { - for (ix = -1022,i=(hx<<11); i>0; i<<=1) ix -=1; - } - } else ix = (hx>>20)-1023; + if(hx<0x00100000) + ix = subnormal_ilogb(hx, lx); + else + ix = (hx>>20)-1023; /* determine iy = ilogb(y) */ - if(hy<0x00100000) { /* subnormal y */ - if(hy==0) { - for (iy = -1043, i=ly; i>0; i<<=1) iy -=1; - } else { - for (iy = -1022,i=(hy<<11); i>0; i<<=1) iy -=1; - } - } else iy = (hy>>20)-1023; + if(hy<0x00100000) + iy = subnormal_ilogb(hy, ly); + else + iy = (hy>>20)-1023; /* set up {hx,lx}, {hy,ly} and align y to x */ - if(ix >= -1022) + if(ix >= -1022) hx = 0x00100000|(0x000fffff&hx); else { /* subnormal x, shift x to normal */ n = -1022-ix; @@ -83,7 +77,7 @@ remquo(double x, double y, int *quo) lx = 0; } } - if(iy >= -1022) + if(iy >= -1022) hy = 0x00100000|(0x000fffff&hy); else { /* subnormal y, shift y to normal */ n = -1022-iy; diff --git a/lib/msun/src/s_remquof.c b/lib/msun/src/s_remquof.c index 9cd148586796..e4adb8321559 100644 --- a/lib/msun/src/s_remquof.c +++ b/lib/msun/src/s_remquof.c @@ -25,7 +25,7 @@ static const float Zero[] = {0.0, -0.0,}; float remquof(float x, float y, int *quo) { - int32_t n,hx,hy,hz,ix,iy,sx,i; + int32_t hx, hy, hz, ix, iy, n, sx; u_int32_t q,sxy; GET_FLOAT_WORD(hx,x); @@ -47,14 +47,16 @@ remquof(float x, float y, int *quo) } /* determine ix = ilogb(x) */ - if(hx<0x00800000) { /* subnormal x */ - for (ix = -126,i=(hx<<8); i>0; i<<=1) ix -=1; - } else ix = (hx>>23)-127; + if(hx<0x00800000) + ix = subnormal_ilogbf(hx); + else + ix = (hx>>23)-127; /* determine iy = ilogb(y) */ - if(hy<0x00800000) { /* subnormal y */ - for (iy = -126,i=(hy<<8); i>0; i<<=1) iy -=1; - } else iy = (hy>>23)-127; + if(hy<0x00800000) + iy = subnormal_ilogbf(hy); + else + iy = (hy>>23)-127; /* set up {hx,lx}, {hy,ly} and align y to x */ if(ix >= -126) |