mirror of
https://git.freebsd.org/src.git
synced 2026-01-11 19:57:22 +00:00
Revert "Remove Secure RPC DES authentication"
This reverts commit 7ac276298b.
Requested by: kib
This commit is contained in:
parent
429152cb04
commit
837b13af68
32 changed files with 3141 additions and 108 deletions
|
|
@ -54,10 +54,6 @@
|
|||
# 20250812: Remove a bogus manlink
|
||||
OLD_FILES+=usr/share/man/man3/quota_statfs.3.gz
|
||||
|
||||
# 20250810: Removal of remaining Secure RPC (DES) bits
|
||||
OLD_FILES+=usr/sbin/rpc.ypupdated
|
||||
OLD_FILES+=etc/rc.d/ypupdated
|
||||
|
||||
# 20250808: nvmfd removed from base install
|
||||
OLD_FILES+=usr/sbin/nvmfd
|
||||
OLD_FILES+=usr/share/man/man8/nvmfd.8.gz
|
||||
|
|
|
|||
6
RELNOTES
6
RELNOTES
|
|
@ -16,12 +16,6 @@ cce64f2e6851:
|
|||
This only works for exported ZFS file systems that have
|
||||
block cloning enabled, at this time.
|
||||
|
||||
7ac276298b72, 7b8c9de17448, 1271b1d747a7, 9dcb984251b3:
|
||||
Support for Secure RPC DES authentication has been removed. This
|
||||
includes publickey(5), keyserv(8) and the rpc_secure(3) routines which
|
||||
rely on keyserv. The libc symbols are still present for backward
|
||||
compatibility, but all functions will unconditionally return an error.
|
||||
|
||||
37b2cb5ecb0f:
|
||||
Add support to VOP_COPY_FILE_RANGE() for block cloning.
|
||||
At this time, ZFS is the only local file system that supports
|
||||
|
|
|
|||
4
UPDATING
4
UPDATING
|
|
@ -27,6 +27,10 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 15.x IS SLOW:
|
|||
world, or to merely disable the most expensive debugging functionality
|
||||
at runtime, run "ln -s 'abort:false,junk:false' /etc/malloc.conf".)
|
||||
|
||||
20250815:
|
||||
The removal of Secure RPC DES authentication notced in 20250810
|
||||
has been reverted. (However, it is still non-functional.)
|
||||
|
||||
20250813:
|
||||
Commit cce64f2e6851 changed the internal KAPI between the NFS
|
||||
modules. As such, all of them need to be rebuilt from sources.
|
||||
|
|
|
|||
|
|
@ -33,14 +33,91 @@
|
|||
* Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
/* Note, RPC DES authentication was removed in FreeBSD 15.0. */
|
||||
/*
|
||||
* auth_des.h, Protocol for DES style authentication for RPC
|
||||
*/
|
||||
|
||||
#ifndef _AUTH_DES_
|
||||
#define _AUTH_DES_
|
||||
|
||||
/*
|
||||
* There are two kinds of "names": fullnames and nicknames
|
||||
*/
|
||||
enum authdes_namekind {
|
||||
ADN_FULLNAME,
|
||||
ADN_NICKNAME
|
||||
};
|
||||
|
||||
/*
|
||||
* A fullname contains the network name of the client,
|
||||
* a conversation key and the window
|
||||
*/
|
||||
struct authdes_fullname {
|
||||
char *name; /* network name of client, up to MAXNETNAMELEN */
|
||||
des_block key; /* conversation key */
|
||||
u_long window; /* associated window */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* A credential
|
||||
*/
|
||||
struct authdes_cred {
|
||||
enum authdes_namekind adc_namekind;
|
||||
struct authdes_fullname adc_fullname;
|
||||
u_long adc_nickname;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* A des authentication verifier
|
||||
*/
|
||||
struct authdes_verf {
|
||||
union {
|
||||
struct timeval adv_ctime; /* clear time */
|
||||
des_block adv_xtime; /* crypt time */
|
||||
} adv_time_u;
|
||||
u_long adv_int_u;
|
||||
};
|
||||
|
||||
/*
|
||||
* des authentication verifier: client variety
|
||||
*
|
||||
* adv_timestamp is the current time.
|
||||
* adv_winverf is the credential window + 1.
|
||||
* Both are encrypted using the conversation key.
|
||||
*/
|
||||
#define adv_timestamp adv_time_u.adv_ctime
|
||||
#define adv_xtimestamp adv_time_u.adv_xtime
|
||||
#define adv_winverf adv_int_u
|
||||
|
||||
/*
|
||||
* des authentication verifier: server variety
|
||||
*
|
||||
* adv_timeverf is the client's timestamp + client's window
|
||||
* adv_nickname is the server's nickname for the client.
|
||||
* adv_timeverf is encrypted using the conversation key.
|
||||
*/
|
||||
#define adv_timeverf adv_time_u.adv_ctime
|
||||
#define adv_xtimeverf adv_time_u.adv_xtime
|
||||
#define adv_nickname adv_int_u
|
||||
|
||||
/*
|
||||
* Map a des credential into a unix cred.
|
||||
*
|
||||
*/
|
||||
__BEGIN_DECLS
|
||||
extern int authdes_getucred( struct authdes_cred *, uid_t *, gid_t *, int *, gid_t * );
|
||||
__END_DECLS
|
||||
|
||||
__BEGIN_DECLS
|
||||
extern bool_t xdr_authdes_cred(XDR *, struct authdes_cred *);
|
||||
extern bool_t xdr_authdes_verf(XDR *, struct authdes_verf *);
|
||||
extern int rtime(dev_t, struct netbuf *, int, struct timeval *,
|
||||
struct timeval *);
|
||||
extern void kgetnetname(char *);
|
||||
extern enum auth_stat _svcauth_des(struct svc_req *, struct rpc_msg *);
|
||||
__END_DECLS
|
||||
|
||||
#endif /* ndef _AUTH_DES_ */
|
||||
|
|
|
|||
|
|
@ -8,9 +8,13 @@ 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;
|
||||
|
|
@ -54,6 +58,15 @@ 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;
|
||||
|
|
@ -117,6 +130,7 @@ FBSD_1.0 {
|
|||
callrpc;
|
||||
registerrpc;
|
||||
clnt_broadcast;
|
||||
authdes_create;
|
||||
clntunix_create;
|
||||
svcunix_create;
|
||||
svcunixfd_create;
|
||||
|
|
@ -166,6 +180,8 @@ FBSD_1.0 {
|
|||
_authenticate;
|
||||
_svcauth_null;
|
||||
svc_auth_reg;
|
||||
_svcauth_des;
|
||||
authdes_getucred;
|
||||
_svcauth_unix;
|
||||
_svcauth_short;
|
||||
svc_dg_create;
|
||||
|
|
@ -189,6 +205,9 @@ 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;
|
||||
|
|
|
|||
|
|
@ -30,34 +30,463 @@
|
|||
/*
|
||||
* Copyright (c) 1988 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* auth_des.c, client-side implementation of DES authentication
|
||||
*/
|
||||
|
||||
#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"
|
||||
|
||||
static AUTH *
|
||||
__authdes_seccreate(const char *servername, const u_int win,
|
||||
#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,
|
||||
const char *timehost, const des_block *ckey)
|
||||
{
|
||||
return (NULL);
|
||||
}
|
||||
__sym_compat(authdes_seccreate, __authdes_seccreate, FBSD_1.0);
|
||||
u_char pkey_data[1024];
|
||||
netobj pkey;
|
||||
AUTH *dummy;
|
||||
|
||||
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)
|
||||
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_pk_seccreate, __authdes_pk_seccreate, FBSD_1.0);
|
||||
|
||||
/*
|
||||
* Implement the five authentication operations
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* 1. Next Verifier
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
static void
|
||||
authdes_nextverf(AUTH *auth __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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,16 +42,44 @@
|
|||
#include <rpc/auth_des.h>
|
||||
#include "un-namespace.h"
|
||||
|
||||
static bool_t
|
||||
__xdr_authdes_cred(XDR *xdrs, void *cred)
|
||||
{
|
||||
return (FALSE);
|
||||
}
|
||||
__sym_compat(xdr_authdes_cred, __xdr_authdes_cred, FBSD_1.0);
|
||||
#define ATTEMPT(xdr_op) if (!(xdr_op)) return (FALSE)
|
||||
|
||||
static bool_t
|
||||
__xdr_authdes_verf(XDR *xdrs, void *verf)
|
||||
bool_t
|
||||
xdr_authdes_cred(XDR *xdrs, struct authdes_cred *cred)
|
||||
{
|
||||
return (FALSE);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool_t
|
||||
xdr_authdes_verf(XDR *xdrs, struct authdes_verf *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);
|
||||
}
|
||||
__sym_compat(xdr_authdes_verf, __xdr_authdes_verf, FBSD_1.0);
|
||||
|
|
|
|||
|
|
@ -32,78 +32,426 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
#include "reentrant.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/key_prot.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 "un-namespace.h"
|
||||
#include "mt_misc.h"
|
||||
|
||||
static int
|
||||
__key_setsecret(const char *secretkey)
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
__sym_compat(key_setsecret, __key_setsecret, FBSD_1.0);
|
||||
|
||||
static int
|
||||
__key_secretkey_is_set(void)
|
||||
#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);
|
||||
}
|
||||
__sym_compat(key_secretkey_is_set, __key_secretkey_is_set, FBSD_1.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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
int
|
||||
key_decryptsession(const char *remotename, des_block *deskey)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
int
|
||||
key_gendes(des_block *key)
|
||||
{
|
||||
if (!key_call((u_long)KEY_GEN, (xdrproc_t)xdr_void, NULL,
|
||||
(xdrproc_t)xdr_des_block, key)) {
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
key_setnet(struct key_netstarg *arg)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
key_get_conv(char *pkey, 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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct key_call_private *kcp = (struct key_call_private *)vp;
|
||||
|
||||
if (kcp) {
|
||||
if (kcp->client)
|
||||
clnt_destroy(kcp->client);
|
||||
free(kcp);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
key_call_init(void)
|
||||
{
|
||||
|
||||
key_call_key_error = thr_keycreate(&key_call_key, key_call_destroy);
|
||||
}
|
||||
|
||||
/*
|
||||
* Keep the handle cached. This call may be made quite often.
|
||||
*/
|
||||
static CLIENT *
|
||||
getkeyserv_handle(int vers)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/* returns 0 on failure, 1 on success */
|
||||
|
||||
static int
|
||||
__key_encryptsession_pk(char *remotename, netobj *remotekey, des_block *deskey)
|
||||
key_call(u_long proc, xdrproc_t xdr_arg, void *arg, xdrproc_t xdr_rslt,
|
||||
void *rslt)
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
__sym_compat(key_encryptsession_pk, __key_encryptsession_pk, FBSD_1.0);
|
||||
CLIENT *clnt;
|
||||
struct timeval wait_time;
|
||||
|
||||
static int
|
||||
__key_decryptsession_pk(char *remotename, netobj *remotekey, des_block *deskey)
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
__sym_compat(key_decryptsession_pk, __key_decryptsession_pk, FBSD_1.0);
|
||||
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);
|
||||
}
|
||||
|
||||
static int
|
||||
__key_encryptsession(const char *remotename, des_block *deskey)
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
__sym_compat(key_encryptsession, __key_encryptsession, FBSD_1.0);
|
||||
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 */
|
||||
|
||||
static int
|
||||
__key_decryptsession(const char *remotename, des_block *deskey)
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
__sym_compat(key_decryptsession, __key_decryptsession, FBSD_1.0);
|
||||
if (clnt == NULL) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
__key_gendes(des_block *key)
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
__sym_compat(key_gendes, __key_gendes, FBSD_1.0);
|
||||
wait_time.tv_sec = TOTAL_TIMEOUT;
|
||||
wait_time.tv_usec = 0;
|
||||
|
||||
static int
|
||||
__key_setnet(struct key_netstarg *arg)
|
||||
{
|
||||
return (-1);
|
||||
if (clnt_call(clnt, proc, xdr_arg, arg, xdr_rslt, rslt,
|
||||
wait_time) == RPC_SUCCESS) {
|
||||
return (1);
|
||||
} else {
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
__sym_compat(key_setnet, __key_setnet, FBSD_1.0);
|
||||
|
||||
static int
|
||||
__key_get_conv(char *pkey, des_block *deskey)
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
__sym_compat(key_get_conv, __key_get_conv, FBSD_1.0);
|
||||
|
|
|
|||
40
lib/libc/rpc/publickey.5
Normal file
40
lib/libc/rpc/publickey.5
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
.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
|
||||
|
|
@ -1,17 +1,34 @@
|
|||
.\"
|
||||
.Dd August 10, 2025
|
||||
.Dt RPC_SECURE 3
|
||||
.Dd February 16, 1988
|
||||
.Dt RPC 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"
|
||||
|
|
@ -21,11 +38,101 @@
|
|||
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
|
||||
|
|
@ -54,6 +161,72 @@ 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
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
.\" $NetBSD: rpc_soc.3,v 1.2 2000/06/07 13:39:43 simonb Exp $
|
||||
.\"
|
||||
.Dd August 10, 2025
|
||||
.Dd February 16, 1988
|
||||
.Dt RPC_SOC 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
|
@ -100,6 +100,16 @@ 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
|
||||
|
|
@ -1691,6 +1701,7 @@ 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"
|
||||
|
|
|
|||
|
|
@ -379,13 +379,36 @@ clnt_broadcast(u_long prog, u_long vers, u_long proc, xdrproc_t xargs,
|
|||
* Create the client des authentication object. Obsoleted by
|
||||
* authdes_seccreate().
|
||||
*/
|
||||
static AUTH *
|
||||
__authdes_create(char *servername, u_int window, struct sockaddr *syncaddr,
|
||||
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
|
||||
*/
|
||||
{
|
||||
return (NULL);
|
||||
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);
|
||||
}
|
||||
__sym_compat(authdes_create, __authdes_create, FBSD_1.0);
|
||||
|
||||
/*
|
||||
* Create a client handle for a unix connection. Obsoleted by clnt_vc_create()
|
||||
|
|
|
|||
|
|
@ -114,6 +114,11 @@ _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;
|
||||
}
|
||||
|
|
@ -181,6 +186,9 @@ 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);
|
||||
|
||||
|
|
|
|||
|
|
@ -34,8 +34,17 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* svcauth_des.c, server-side des authentication.
|
||||
* This functionality was removed in FreeBSD 15.0.
|
||||
* 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 .
|
||||
*
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
|
|
@ -56,16 +65,384 @@
|
|||
#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
|
||||
*/
|
||||
static enum auth_stat
|
||||
__svcauth_des(struct svc_req *rqst, struct rpc_msg *msg)
|
||||
enum auth_stat
|
||||
_svcauth_des(struct svc_req *rqst, struct rpc_msg *msg)
|
||||
{
|
||||
return (AUTH_FAILED);
|
||||
}
|
||||
__sym_compat(_svcauth_des, __svcauth_des, FBSD_1.0);
|
||||
|
||||
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!*/
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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.
|
||||
|
|
@ -73,10 +450,73 @@ __sym_compat(_svcauth_des, __svcauth_des, FBSD_1.0);
|
|||
* not have to make an rpc call every time to interpret
|
||||
* the credential.
|
||||
*/
|
||||
static int
|
||||
__authdes_getucred(void *adc, uid_t *uid, gid_t *gid,
|
||||
int
|
||||
authdes_getucred(struct authdes_cred *adc, uid_t *uid, gid_t *gid,
|
||||
int *grouplen, gid_t *groups)
|
||||
{
|
||||
return (0);
|
||||
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);
|
||||
}
|
||||
__sym_compat(authdes_getucred, __authdes_getucred, FBSD_1.0);
|
||||
|
||||
static void
|
||||
invalidate(char *cred)
|
||||
{
|
||||
if (cred == NULL) {
|
||||
return;
|
||||
}
|
||||
((struct bsdcred *)cred)->grouplen = INVALID;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ OTHERSRCS= rnusers.c rstat.c rwall.c
|
|||
SECRPCSRCS= secretkey.c xcrypt.c
|
||||
|
||||
.if ${MK_NIS} != "no"
|
||||
OTHERSRCS+= yp_passwd.c
|
||||
OTHERSRCS+= yp_passwd.c yp_update.c
|
||||
.endif
|
||||
|
||||
RPCCOM= RPCGEN_CPP=${CPP:Q} rpcgen -C
|
||||
|
|
|
|||
199
lib/librpcsvc/yp_update.c
Normal file
199
lib/librpcsvc/yp_update.c
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
/*-
|
||||
* 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);
|
||||
}
|
||||
|
|
@ -396,6 +396,7 @@ rpc_statd_flags="" # Flags to rpc.statd (if enabled).
|
|||
rpcbind_enable="NO" # Run the portmapper service (YES/NO).
|
||||
rpcbind_program="/usr/sbin/rpcbind" # path to rpcbind, if you want a different one.
|
||||
rpcbind_flags="" # Flags to rpcbind (if enabled).
|
||||
rpc_ypupdated_enable="NO" # Run if NIS master and SecureRPC (or NO).
|
||||
nfsv4_server_enable="NO" # Enable support for NFSv4
|
||||
nfsv4_server_only="NO" # Set NFS server to NFSv4 only
|
||||
nfscbd_enable="NO" # NFSv4 client side callback daemon
|
||||
|
|
|
|||
|
|
@ -318,6 +318,7 @@ YP= ypbind \
|
|||
yppasswdd \
|
||||
ypserv \
|
||||
ypset \
|
||||
ypupdated \
|
||||
ypxfrd \
|
||||
nisdomain
|
||||
YPPACKAGE= yp
|
||||
|
|
|
|||
35
libexec/rc/rc.d/ypupdated
Executable file
35
libexec/rc/rc.d/ypupdated
Executable file
|
|
@ -0,0 +1,35 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
#
|
||||
|
||||
# PROVIDE: ypupdated
|
||||
# REQUIRE: rpcbind ypserv
|
||||
# KEYWORD: shutdown
|
||||
|
||||
. /etc/rc.subr
|
||||
|
||||
name="ypupdated"
|
||||
rcvar="rpc_ypupdated_enable"
|
||||
|
||||
: ${ypupdated_svcj_options:="net_basic"}
|
||||
|
||||
load_rc_config $name
|
||||
|
||||
command="/usr/sbin/rpc.${name}"
|
||||
start_precmd="rpc_ypupdated_precmd"
|
||||
|
||||
rpc_ypupdated_precmd()
|
||||
{
|
||||
local _domain
|
||||
|
||||
force_depend rpcbind || return 1
|
||||
force_depend ypserv nis_server || return 1
|
||||
|
||||
_domain=`domainname`
|
||||
if [ -z "$_domain" ]; then
|
||||
warn "NIS domainname(1) is not set."
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
run_rc_command "$1"
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd August 10, 2025
|
||||
.Dd July 15, 2025
|
||||
.Dt RC.CONF 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
|
@ -2932,6 +2932,13 @@ is set to
|
|||
these are the flags to pass to the
|
||||
.Xr rpc.yppasswdd 8
|
||||
daemon.
|
||||
.It Va rpc_ypupdated_enable
|
||||
.Pq Vt bool
|
||||
If set to
|
||||
.Dq Li YES ,
|
||||
run the
|
||||
.Nm rpc.ypupdated
|
||||
daemon at system boot time.
|
||||
.It Va bsnmpd_enable
|
||||
.Pq Vt bool
|
||||
If set to
|
||||
|
|
|
|||
|
|
@ -246,6 +246,19 @@ extern AUTH *authunix_create_default(void); /* takes no parameters */
|
|||
extern AUTH *authnone_create(void); /* takes no parameters */
|
||||
extern AUTH *authtls_create(void); /* takes no parameters */
|
||||
__END_DECLS
|
||||
/*
|
||||
* DES style authentication
|
||||
* AUTH *authsecdes_create(servername, window, timehost, ckey)
|
||||
* char *servername; - network name of server
|
||||
* u_int window; - time to live
|
||||
* const char *timehost; - optional hostname to sync with
|
||||
* des_block *ckey; - optional conversation key to use
|
||||
*/
|
||||
__BEGIN_DECLS
|
||||
extern AUTH *authdes_create (char *, u_int, struct sockaddr *, des_block *);
|
||||
extern AUTH *authdes_seccreate (const char *, const u_int, const char *,
|
||||
const des_block *);
|
||||
__END_DECLS
|
||||
|
||||
__BEGIN_DECLS
|
||||
extern bool_t xdr_opaque_auth (XDR *, struct opaque_auth *);
|
||||
|
|
@ -266,6 +279,19 @@ extern int netname2host(char *, char *, const int);
|
|||
extern void passwd2des ( char *, char * );
|
||||
__END_DECLS
|
||||
|
||||
/*
|
||||
*
|
||||
* These routines interface to the keyserv daemon
|
||||
*
|
||||
*/
|
||||
__BEGIN_DECLS
|
||||
extern int key_decryptsession(const char *, des_block *);
|
||||
extern int key_encryptsession(const char *, des_block *);
|
||||
extern int key_gendes(des_block *);
|
||||
extern int key_setsecret(const char *);
|
||||
extern int key_secretkey_is_set(void);
|
||||
__END_DECLS
|
||||
|
||||
/*
|
||||
* Publickey routines.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -8874,6 +8874,7 @@ OLD_FILES+=etc/rc.d/ypldap
|
|||
OLD_FILES+=etc/rc.d/yppasswdd
|
||||
OLD_FILES+=etc/rc.d/ypserv
|
||||
OLD_FILES+=etc/rc.d/ypset
|
||||
OLD_FILES+=etc/rc.d/ypupdated
|
||||
OLD_FILES+=etc/rc.d/ypxfrd
|
||||
OLD_FILES+=usr/bin/ypcat
|
||||
OLD_FILES+=usr/bin/ypchfn
|
||||
|
|
@ -8891,6 +8892,7 @@ OLD_FILES+=usr/libexec/mknetid
|
|||
OLD_FILES+=usr/libexec/yppwupdate
|
||||
OLD_FILES+=usr/libexec/ypxfr
|
||||
OLD_FILES+=usr/sbin/rpc.yppasswdd
|
||||
OLD_FILES+=usr/sbin/rpc.ypupdated
|
||||
OLD_FILES+=usr/sbin/rpc.ypxfrd
|
||||
OLD_FILES+=usr/sbin/yp_mkdb
|
||||
OLD_FILES+=usr/sbin/ypbind
|
||||
|
|
|
|||
|
|
@ -174,6 +174,7 @@ SUBDIR.${MK_NETGRAPH}+= flowctl
|
|||
SUBDIR.${MK_NETGRAPH}+= ngctl
|
||||
SUBDIR.${MK_NETGRAPH}+= nghook
|
||||
SUBDIR.${MK_NIS}+= rpc.yppasswdd
|
||||
SUBDIR.${MK_NIS}+= rpc.ypupdated
|
||||
SUBDIR.${MK_NIS}+= rpc.ypxfrd
|
||||
SUBDIR.${MK_NIS}+= ypbind
|
||||
SUBDIR.${MK_NIS}+= ypldap
|
||||
|
|
|
|||
32
usr.sbin/rpc.ypupdated/Makefile
Normal file
32
usr.sbin/rpc.ypupdated/Makefile
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
.PATH: ${SRCTOP}/usr.sbin/ypserv ${SRCTOP}/libexec/ypxfr
|
||||
|
||||
PACKAGE=yp
|
||||
PROG= rpc.ypupdated
|
||||
MAN=
|
||||
SRCS= ypupdate_prot_svc.c ypupdate_prot.h ypupdated_main.c \
|
||||
yp_error.c update.c ypupdated_server.c \
|
||||
yp_dblookup.c yp_dbwrite.c yp_dbdelete.c yp_dbupdate.c
|
||||
|
||||
#CFLAGS+= -DYP
|
||||
CFLAGS+= -I${SRCTOP}/usr.sbin/ypserv -I. -I${SRCTOP}/libexec/ypxfr
|
||||
|
||||
WARNS?= 1
|
||||
|
||||
LIBADD= rpcsvc
|
||||
|
||||
CLEANFILES= ypupdate_prot_svc.c ypupdate_prot.h
|
||||
|
||||
RPCDIR= ${SYSROOT:U${DESTDIR}}/usr/include/rpcsvc
|
||||
RPCGEN= RPCGEN_CPP=${CPP:Q} rpcgen -I -C
|
||||
|
||||
# We need to remove the 'static' keyword from _rpcsvcstate so that
|
||||
# ypupdated_main.c can see it.
|
||||
ypupdate_prot_svc.c: ${RPCDIR}/ypupdate_prot.x
|
||||
rm -f ${.TARGET}
|
||||
${RPCGEN} -m ${.ALLSRC} | \
|
||||
sed s/"static int _rpcsvcstate"/"int _rpcsvcstate"/g > ${.TARGET}
|
||||
|
||||
ypupdate_prot.h: ${RPCDIR}/ypupdate_prot.x
|
||||
${RPCGEN} -h -o ${.TARGET} ${.ALLSRC}
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
18
usr.sbin/rpc.ypupdated/Makefile.depend
Normal file
18
usr.sbin/rpc.ypupdated/Makefile.depend
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# Autogenerated - do NOT edit!
|
||||
|
||||
DIRDEPS = \
|
||||
include \
|
||||
include/rpc \
|
||||
include/rpcsvc \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
lib/libc \
|
||||
lib/libcompiler_rt \
|
||||
lib/librpcsvc \
|
||||
|
||||
|
||||
.include <dirdeps.mk>
|
||||
|
||||
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
|
||||
# local dependencies - needed for -jN in clean tree
|
||||
.endif
|
||||
328
usr.sbin/rpc.ypupdated/update.c
Normal file
328
usr.sbin/rpc.ypupdated/update.c
Normal file
|
|
@ -0,0 +1,328 @@
|
|||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user or with the express written consent of
|
||||
* Sun Microsystems, Inc.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 1986, 1989, Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Administrative tool to add a new user to the publickey database
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/key_prot.h>
|
||||
#ifdef YP
|
||||
#include <rpcsvc/yp_prot.h>
|
||||
#include <rpcsvc/ypclnt.h>
|
||||
#include <sys/wait.h>
|
||||
#include <netdb.h>
|
||||
#endif /* YP */
|
||||
#include <pwd.h>
|
||||
#include <string.h>
|
||||
#include <sys/resource.h>
|
||||
#include "ypupdated_extern.h"
|
||||
|
||||
#ifdef YP
|
||||
#define MAXMAPNAMELEN 256
|
||||
#else
|
||||
#define YPOP_CHANGE 1 /* change, do not add */
|
||||
#define YPOP_INSERT 2 /* add, do not change */
|
||||
#define YPOP_DELETE 3 /* delete this entry */
|
||||
#define YPOP_STORE 4 /* add, or change */
|
||||
#endif
|
||||
|
||||
#ifdef YP
|
||||
static char SHELL[] = "/bin/sh";
|
||||
static char YPDBPATH[]="/var/yp"; /* This is defined but not used! */
|
||||
static char PKMAP[] = "publickey.byname";
|
||||
static char UPDATEFILE[] = "updaters";
|
||||
static char PKFILE[] = "/etc/publickey";
|
||||
#endif /* YP */
|
||||
|
||||
#ifdef YP
|
||||
static int _openchild(char *, FILE **, FILE **);
|
||||
|
||||
/*
|
||||
* Determine if requester is allowed to update the given map,
|
||||
* and update it if so. Returns the yp status, which is zero
|
||||
* if there is no access violation.
|
||||
*/
|
||||
int
|
||||
mapupdate(char *requester, char *mapname, u_int op, u_int keylen, char *key,
|
||||
u_int datalen, char *data)
|
||||
{
|
||||
char updater[MAXMAPNAMELEN + 40];
|
||||
FILE *childargs;
|
||||
FILE *childrslt;
|
||||
#ifdef WEXITSTATUS
|
||||
int status;
|
||||
#else
|
||||
union wait status;
|
||||
#endif
|
||||
pid_t pid;
|
||||
u_int yperrno;
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("%s %s\n", key, data);
|
||||
#endif
|
||||
(void)sprintf(updater, "make -s -f %s/%s %s", YPDBPATH, /* !!! */
|
||||
UPDATEFILE, mapname);
|
||||
pid = _openchild(updater, &childargs, &childrslt);
|
||||
if (pid < 0) {
|
||||
return (YPERR_YPERR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write to child
|
||||
*/
|
||||
(void)fprintf(childargs, "%s\n", requester);
|
||||
(void)fprintf(childargs, "%u\n", op);
|
||||
(void)fprintf(childargs, "%u\n", keylen);
|
||||
(void)fwrite(key, (int)keylen, 1, childargs);
|
||||
(void)fprintf(childargs, "\n");
|
||||
(void)fprintf(childargs, "%u\n", datalen);
|
||||
(void)fwrite(data, (int)datalen, 1, childargs);
|
||||
(void)fprintf(childargs, "\n");
|
||||
(void)fclose(childargs);
|
||||
|
||||
/*
|
||||
* Read from child
|
||||
*/
|
||||
(void)fscanf(childrslt, "%d", &yperrno);
|
||||
(void)fclose(childrslt);
|
||||
|
||||
(void)wait(&status);
|
||||
#ifdef WEXITSTATUS
|
||||
if (WEXITSTATUS(status) != 0)
|
||||
#else
|
||||
if (status.w_retcode != 0)
|
||||
#endif
|
||||
return (YPERR_YPERR);
|
||||
return (yperrno);
|
||||
}
|
||||
|
||||
/*
|
||||
* returns pid, or -1 for failure
|
||||
*/
|
||||
static int
|
||||
_openchild(char *command, FILE **fto, FILE **ffrom)
|
||||
{
|
||||
int i;
|
||||
pid_t pid;
|
||||
int pdto[2];
|
||||
int pdfrom[2];
|
||||
char *com;
|
||||
struct rlimit rl;
|
||||
|
||||
if (pipe(pdto) < 0) {
|
||||
goto error1;
|
||||
}
|
||||
if (pipe(pdfrom) < 0) {
|
||||
goto error2;
|
||||
}
|
||||
switch (pid = fork()) {
|
||||
case -1:
|
||||
goto error3;
|
||||
|
||||
case 0:
|
||||
/*
|
||||
* child: read from pdto[0], write into pdfrom[1]
|
||||
*/
|
||||
(void)close(0);
|
||||
(void)dup(pdto[0]);
|
||||
(void)close(1);
|
||||
(void)dup(pdfrom[1]);
|
||||
getrlimit(RLIMIT_NOFILE, &rl);
|
||||
for (i = rl.rlim_max - 1; i >= 3; i--) {
|
||||
(void) close(i);
|
||||
}
|
||||
com = malloc((unsigned) strlen(command) + 6);
|
||||
if (com == NULL) {
|
||||
_exit(~0);
|
||||
}
|
||||
(void)sprintf(com, "exec %s", command);
|
||||
execl(SHELL, basename(SHELL), "-c", com, (char *)NULL);
|
||||
_exit(~0);
|
||||
|
||||
default:
|
||||
/*
|
||||
* parent: write into pdto[1], read from pdfrom[0]
|
||||
*/
|
||||
*fto = fdopen(pdto[1], "w");
|
||||
(void)close(pdto[0]);
|
||||
*ffrom = fdopen(pdfrom[0], "r");
|
||||
(void)close(pdfrom[1]);
|
||||
break;
|
||||
}
|
||||
return (pid);
|
||||
|
||||
/*
|
||||
* error cleanup and return
|
||||
*/
|
||||
error3:
|
||||
(void)close(pdfrom[0]);
|
||||
(void)close(pdfrom[1]);
|
||||
error2:
|
||||
(void)close(pdto[0]);
|
||||
(void)close(pdto[1]);
|
||||
error1:
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static char *
|
||||
basename(char *path)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = strrchr(path, '/');
|
||||
if (p == NULL) {
|
||||
return (path);
|
||||
} else {
|
||||
return (p + 1);
|
||||
}
|
||||
}
|
||||
|
||||
#else /* YP */
|
||||
|
||||
static int match(char *, char *);
|
||||
|
||||
/*
|
||||
* Determine if requester is allowed to update the given map,
|
||||
* and update it if so. Returns the status, which is zero
|
||||
* if there is no access violation. This function updates
|
||||
* the local file and then shuts up.
|
||||
*/
|
||||
int
|
||||
localupdate(char *name, char *filename, u_int op, u_int keylen __unused,
|
||||
char *key, u_int datalen __unused, char *data)
|
||||
{
|
||||
char line[256];
|
||||
FILE *rf;
|
||||
FILE *wf;
|
||||
char *tmpname;
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Check permission
|
||||
*/
|
||||
if (strcmp(name, key) != 0) {
|
||||
return (ERR_ACCESS);
|
||||
}
|
||||
if (strcmp(name, "nobody") == 0) {
|
||||
/*
|
||||
* Can't change "nobody"s key.
|
||||
*/
|
||||
return (ERR_ACCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Open files
|
||||
*/
|
||||
tmpname = malloc(strlen(filename) + 4);
|
||||
if (tmpname == NULL) {
|
||||
return (ERR_MALLOC);
|
||||
}
|
||||
sprintf(tmpname, "%s.tmp", filename);
|
||||
rf = fopen(filename, "r");
|
||||
if (rf == NULL) {
|
||||
err = ERR_READ;
|
||||
goto cleanup;
|
||||
}
|
||||
wf = fopen(tmpname, "w");
|
||||
if (wf == NULL) {
|
||||
fclose(rf);
|
||||
err = ERR_WRITE;
|
||||
goto cleanup;
|
||||
}
|
||||
err = -1;
|
||||
while (fgets(line, sizeof (line), rf)) {
|
||||
if (err < 0 && match(line, name)) {
|
||||
switch (op) {
|
||||
case YPOP_INSERT:
|
||||
err = ERR_KEY;
|
||||
break;
|
||||
case YPOP_STORE:
|
||||
case YPOP_CHANGE:
|
||||
fprintf(wf, "%s %s\n", key, data);
|
||||
err = 0;
|
||||
break;
|
||||
case YPOP_DELETE:
|
||||
/* do nothing */
|
||||
err = 0;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
fputs(line, wf);
|
||||
}
|
||||
}
|
||||
if (err < 0) {
|
||||
switch (op) {
|
||||
case YPOP_CHANGE:
|
||||
case YPOP_DELETE:
|
||||
err = ERR_KEY;
|
||||
break;
|
||||
case YPOP_INSERT:
|
||||
case YPOP_STORE:
|
||||
err = 0;
|
||||
fprintf(wf, "%s %s\n", key, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(wf);
|
||||
fclose(rf);
|
||||
if (err == 0) {
|
||||
if (rename(tmpname, filename) < 0) {
|
||||
err = ERR_DBASE;
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
if (unlink(tmpname) < 0) {
|
||||
err = ERR_DBASE;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
cleanup:
|
||||
free(tmpname);
|
||||
return (err);
|
||||
}
|
||||
|
||||
static int
|
||||
match(char *line, char *name)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = strlen(name);
|
||||
return (strncmp(line, name, len) == 0 &&
|
||||
(line[len] == ' ' || line[len] == '\t'));
|
||||
}
|
||||
#endif /* !YP */
|
||||
68
usr.sbin/rpc.ypupdated/yp_dbdelete.c
Normal file
68
usr.sbin/rpc.ypupdated/yp_dbdelete.c
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/*-
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <db.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <paths.h>
|
||||
#include <rpcsvc/yp.h>
|
||||
#include "ypxfr_extern.h"
|
||||
|
||||
int
|
||||
yp_del_record(DB *dbp, DBT *key)
|
||||
{
|
||||
int rval;
|
||||
|
||||
if ((rval = (dbp->del)(dbp,key,0))) {
|
||||
switch (rval) {
|
||||
case 1:
|
||||
return(YP_FALSE);
|
||||
break;
|
||||
case -1:
|
||||
default:
|
||||
(void)(dbp->close)(dbp);
|
||||
return(YP_BADDB);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return(YP_TRUE);
|
||||
}
|
||||
147
usr.sbin/rpc.ypupdated/yp_dbupdate.c
Normal file
147
usr.sbin/rpc.ypupdated/yp_dbupdate.c
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
/*-
|
||||
* SPDX-License-Identifier: BSD-4-Clause
|
||||
*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/fcntl.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <db.h>
|
||||
#include <unistd.h>
|
||||
#include <rpcsvc/ypclnt.h>
|
||||
#include <rpcsvc/ypupdate_prot.h>
|
||||
#include "ypxfr_extern.h"
|
||||
#include "ypupdated_extern.h"
|
||||
|
||||
static int
|
||||
yp_domake(char *map, char *domain)
|
||||
{
|
||||
int pid;
|
||||
|
||||
switch ((pid = fork())) {
|
||||
case 0:
|
||||
execlp(MAP_UPDATE_PATH, MAP_UPDATE, map, domain, (char *)NULL);
|
||||
yp_error("couldn't exec map update process: %s",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
break;
|
||||
case -1:
|
||||
yp_error("fork() failed: %s", strerror(errno));
|
||||
return(YPERR_YPERR);
|
||||
break;
|
||||
default:
|
||||
children++;
|
||||
break;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
ypmap_update(char *netname, char *map, unsigned int op, unsigned int keylen,
|
||||
char *keyval, unsigned int datlen, char *datval)
|
||||
{
|
||||
DB *dbp;
|
||||
DBT key = { NULL, 0 }, data = { NULL, 0 };
|
||||
char *yp_last = "YP_LAST_MODIFIED";
|
||||
char yplastbuf[32];
|
||||
char *domptr;
|
||||
int rval = 0;
|
||||
|
||||
if ((domptr = strchr(netname, '@')) == NULL)
|
||||
return(ERR_ACCESS);
|
||||
domptr++;
|
||||
|
||||
|
||||
dbp = yp_open_db_rw(domptr, map, O_RDWR);
|
||||
if (dbp == NULL)
|
||||
return(ERR_DBASE);
|
||||
|
||||
key.data = keyval;
|
||||
key.size = keylen;
|
||||
data.data = datval;
|
||||
data.size = datlen;
|
||||
|
||||
switch (op) {
|
||||
case YPOP_DELETE: /* delete this entry */
|
||||
rval = yp_del_record(dbp, &key);
|
||||
if (rval == YP_TRUE)
|
||||
rval = 0;
|
||||
break;
|
||||
case YPOP_INSERT: /* add, do not change */
|
||||
rval = yp_put_record(dbp, &key, &data, 0);
|
||||
if (rval == YP_TRUE)
|
||||
rval = 0;
|
||||
break;
|
||||
case YPOP_STORE: /* add, or change */
|
||||
rval = yp_put_record(dbp, &key, &data, 1);
|
||||
if (rval == YP_TRUE)
|
||||
rval = 0;
|
||||
break;
|
||||
case YPOP_CHANGE: /* change, do not add */
|
||||
if (yp_get_record(domptr, map, &key, &data, 0) != YP_TRUE) {
|
||||
rval = ERR_KEY;
|
||||
break;
|
||||
}
|
||||
rval = yp_put_record(dbp, &key, &data, 1);
|
||||
if (rval == YP_TRUE)
|
||||
rval = 0;
|
||||
break;
|
||||
default:
|
||||
yp_error("unknown update command: (%d)", op);
|
||||
}
|
||||
|
||||
if (rval) {
|
||||
(void)(dbp->close)(dbp);
|
||||
return(rval);
|
||||
}
|
||||
|
||||
snprintf(yplastbuf, sizeof(yplastbuf), "%jd", (intmax_t)time(NULL));
|
||||
key.data = yp_last;
|
||||
key.size = strlen(yp_last);
|
||||
data.data = (char *)&yplastbuf;
|
||||
data.size = strlen(yplastbuf);
|
||||
if (yp_put_record(dbp, &key, &data, 1) != YP_TRUE) {
|
||||
yp_error("failed to update timestamp in %s/%s", domptr, map);
|
||||
(void)(dbp->close)(dbp);
|
||||
return(ERR_DBASE);
|
||||
}
|
||||
|
||||
(void)(dbp->close)(dbp);
|
||||
return(yp_domake(map, domptr));
|
||||
}
|
||||
32
usr.sbin/rpc.ypupdated/ypupdate
Executable file
32
usr.sbin/rpc.ypupdated/ypupdate
Executable file
|
|
@ -0,0 +1,32 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# This script is invoked by rpc.ypupdatedd to propagate NIS maps
|
||||
# after the master map databases have been modified. It expects
|
||||
# to be passed two arguments: the name of the map that was updated
|
||||
# and the name of the domain where the map resides.
|
||||
# These are passed to /var/yp/Makefile.
|
||||
#
|
||||
# Comment out the LOG=yes line to disable logging.
|
||||
#
|
||||
#
|
||||
|
||||
LOG=yes
|
||||
LOGFILE=/var/yp/ypupdate.log
|
||||
|
||||
umask 077
|
||||
|
||||
if [ ! -f $LOGFILE ];
|
||||
then
|
||||
/usr/bin/touch $LOGFILE
|
||||
echo "# Edit /usr/libexec/yppwupdate to disable" >> $LOGFILE
|
||||
echo "# logging to this file from yppasswdd." >> $LOGFILE
|
||||
echo -n "# Log started on: " >> $LOGFILE
|
||||
/bin/date >> $LOGFILE
|
||||
fi
|
||||
|
||||
if [ ! $LOG ];
|
||||
then
|
||||
cd /var/yp/$2; /usr/bin/make -f ../Makefile $1 2>&1
|
||||
else
|
||||
cd /var/yp/$2; /usr/bin/make -f ../Makefile $1 >> $LOGFILE
|
||||
fi
|
||||
32
usr.sbin/rpc.ypupdated/ypupdated_extern.h
Normal file
32
usr.sbin/rpc.ypupdated/ypupdated_extern.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
*/
|
||||
|
||||
#include <db.h>
|
||||
|
||||
#define YPOP_CHANGE 1 /* change, do not add */
|
||||
#define YPOP_INSERT 2 /* add, do not change */
|
||||
#define YPOP_DELETE 3 /* delete this entry */
|
||||
#define YPOP_STORE 4 /* add, or change */
|
||||
|
||||
#define ERR_ACCESS 1
|
||||
#define ERR_MALLOC 2
|
||||
#define ERR_READ 3
|
||||
#define ERR_WRITE 4
|
||||
#define ERR_DBASE 5
|
||||
#define ERR_KEY 6
|
||||
|
||||
#ifndef YPLIBDIR
|
||||
#define YPLIBDIR "/usr/libexec/"
|
||||
#endif
|
||||
|
||||
#ifndef MAP_UPPATE
|
||||
#define MAP_UPDATE "ypupdate"
|
||||
#endif
|
||||
|
||||
#define MAP_UPDATE_PATH YPLIBDIR MAP_UPDATE
|
||||
|
||||
extern int children;
|
||||
extern void ypu_prog_1(struct svc_req *, register SVCXPRT *);
|
||||
extern int localupdate(char *, char *, u_int, u_int, char *, u_int, char *);
|
||||
extern int ypmap_update(char *, char *, u_int, u_int, char *, u_int, char *);
|
||||
extern int yp_del_record(DB *, DBT *);
|
||||
287
usr.sbin/rpc.ypupdated/ypupdated_main.c
Normal file
287
usr.sbin/rpc.ypupdated/ypupdated_main.c
Normal file
|
|
@ -0,0 +1,287 @@
|
|||
/*-
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include "ypupdate_prot.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* getenv, exit */
|
||||
#include <rpc/pmap_clnt.h> /* for pmap_unset */
|
||||
#include <rpc/rpc_com.h>
|
||||
#include <string.h> /* strcmp */
|
||||
#include <signal.h>
|
||||
#ifdef __cplusplus
|
||||
#include <sysent.h> /* getdtablesize, open */
|
||||
#endif /* __cplusplus */
|
||||
#include <memory.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/wait.h>
|
||||
#include <errno.h>
|
||||
#include <err.h>
|
||||
#include <unistd.h>
|
||||
#include "ypupdated_extern.h"
|
||||
#include "yp_extern.h"
|
||||
|
||||
#ifndef SIG_PF
|
||||
#define SIG_PF void(*)(int)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#define RPC_SVC_FG
|
||||
#endif
|
||||
|
||||
#define _RPCSVC_CLOSEDOWN 120
|
||||
int _rpcpmstart; /* Started by a port monitor ? */
|
||||
static int _rpcfdtype;
|
||||
/* Whether Stream or Datagram ? */
|
||||
/* States a server can be in wrt request */
|
||||
|
||||
#define _IDLE 0
|
||||
#define _SERVED 1
|
||||
#define _SERVING 2
|
||||
|
||||
extern int _rpcsvcstate; /* Set when a request is serviced */
|
||||
|
||||
int debug;
|
||||
|
||||
char *progname = "rpc.ypupdated";
|
||||
char *yp_dir = "/var/yp/";
|
||||
|
||||
static void
|
||||
_msgout(char* msg)
|
||||
{
|
||||
#ifdef RPC_SVC_FG
|
||||
if (_rpcpmstart)
|
||||
syslog(LOG_ERR, "%s", msg);
|
||||
else
|
||||
warnx("%s", msg);
|
||||
#else
|
||||
syslog(LOG_ERR, "%s", msg);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
closedown(int sig)
|
||||
{
|
||||
if (_rpcsvcstate == _IDLE) {
|
||||
extern fd_set svc_fdset;
|
||||
static int size;
|
||||
int i, openfd;
|
||||
|
||||
if (_rpcfdtype == SOCK_DGRAM)
|
||||
exit(0);
|
||||
if (size == 0) {
|
||||
size = getdtablesize();
|
||||
}
|
||||
for (i = 0, openfd = 0; i < size && openfd < 2; i++)
|
||||
if (FD_ISSET(i, &svc_fdset))
|
||||
openfd++;
|
||||
if (openfd <= 1)
|
||||
exit(0);
|
||||
}
|
||||
if (_rpcsvcstate == _SERVED)
|
||||
_rpcsvcstate = _IDLE;
|
||||
|
||||
(void) signal(SIGALRM, (SIG_PF) closedown);
|
||||
(void) alarm(_RPCSVC_CLOSEDOWN/2);
|
||||
}
|
||||
|
||||
static void
|
||||
ypupdated_svc_run(void)
|
||||
{
|
||||
#ifdef FD_SETSIZE
|
||||
fd_set readfds;
|
||||
#else
|
||||
int readfds;
|
||||
#endif /* def FD_SETSIZE */
|
||||
extern int forked;
|
||||
int pid;
|
||||
int fd_setsize = _rpc_dtablesize();
|
||||
|
||||
/* Establish the identity of the parent ypupdated process. */
|
||||
pid = getpid();
|
||||
|
||||
for (;;) {
|
||||
#ifdef FD_SETSIZE
|
||||
readfds = svc_fdset;
|
||||
#else
|
||||
readfds = svc_fds;
|
||||
#endif /* def FD_SETSIZE */
|
||||
switch (select(fd_setsize, &readfds, NULL, NULL,
|
||||
(struct timeval *)0)) {
|
||||
case -1:
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
warn("svc_run: - select failed");
|
||||
return;
|
||||
case 0:
|
||||
continue;
|
||||
default:
|
||||
svc_getreqset(&readfds);
|
||||
if (forked && pid != getpid())
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
reaper(int sig)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (sig == SIGHUP) {
|
||||
#ifdef foo
|
||||
load_securenets();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (sig == SIGCHLD) {
|
||||
while (wait3(&status, WNOHANG, NULL) > 0)
|
||||
children--;
|
||||
} else {
|
||||
(void) pmap_unset(YPU_PROG, YPU_VERS);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "rpc.ypupdatedd [-p path]\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
register SVCXPRT *transp = NULL;
|
||||
int sock;
|
||||
int proto = 0;
|
||||
struct sockaddr_in saddr;
|
||||
int asize = sizeof (saddr);
|
||||
int ch;
|
||||
|
||||
while ((ch = getopt(argc, argv, "p:h")) != -1) {
|
||||
switch (ch) {
|
||||
case 'p':
|
||||
yp_dir = optarg;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef foo
|
||||
load_securenets();
|
||||
#endif
|
||||
|
||||
if (svc_auth_reg(AUTH_DES, _svcauth_des) == -1) {
|
||||
yp_error("failed to register AUTH_DES flavor");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {
|
||||
int ssize = sizeof (int);
|
||||
|
||||
if (saddr.sin_family != AF_INET)
|
||||
exit(1);
|
||||
if (getsockopt(0, SOL_SOCKET, SO_TYPE,
|
||||
(char *)&_rpcfdtype, &ssize) == -1)
|
||||
exit(1);
|
||||
sock = 0;
|
||||
_rpcpmstart = 1;
|
||||
proto = 0;
|
||||
openlog("rpc.ypupdatedd", LOG_PID, LOG_DAEMON);
|
||||
} else {
|
||||
#ifndef RPC_SVC_FG
|
||||
if (daemon(0,0)) {
|
||||
err(1, "cannot fork");
|
||||
}
|
||||
openlog("rpc.ypupdated", LOG_PID, LOG_DAEMON);
|
||||
#endif
|
||||
sock = RPC_ANYSOCK;
|
||||
(void) pmap_unset(YPU_PROG, YPU_VERS);
|
||||
}
|
||||
|
||||
if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) {
|
||||
transp = svcudp_create(sock);
|
||||
if (transp == NULL) {
|
||||
_msgout("cannot create udp service.");
|
||||
exit(1);
|
||||
}
|
||||
if (!_rpcpmstart)
|
||||
proto = IPPROTO_UDP;
|
||||
if (!svc_register(transp, YPU_PROG, YPU_VERS, ypu_prog_1, proto)) {
|
||||
_msgout("unable to register (YPU_PROG, YPU_VERS, udp).");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) {
|
||||
transp = svctcp_create(sock, 0, 0);
|
||||
if (transp == NULL) {
|
||||
_msgout("cannot create tcp service.");
|
||||
exit(1);
|
||||
}
|
||||
if (!_rpcpmstart)
|
||||
proto = IPPROTO_TCP;
|
||||
if (!svc_register(transp, YPU_PROG, YPU_VERS, ypu_prog_1, proto)) {
|
||||
_msgout("unable to register (YPU_PROG, YPU_VERS, tcp).");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (transp == (SVCXPRT *)NULL) {
|
||||
_msgout("could not create a handle");
|
||||
exit(1);
|
||||
}
|
||||
if (_rpcpmstart) {
|
||||
(void) signal(SIGALRM, (SIG_PF) closedown);
|
||||
(void) alarm(_RPCSVC_CLOSEDOWN/2);
|
||||
}
|
||||
|
||||
(void) signal(SIGPIPE, SIG_IGN);
|
||||
(void) signal(SIGCHLD, (SIG_PF) reaper);
|
||||
(void) signal(SIGTERM, (SIG_PF) reaper);
|
||||
(void) signal(SIGINT, (SIG_PF) reaper);
|
||||
(void) signal(SIGHUP, (SIG_PF) reaper);
|
||||
|
||||
ypupdated_svc_run();
|
||||
_msgout("svc_run returned");
|
||||
exit(1);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
227
usr.sbin/rpc.ypupdated/ypupdated_server.c
Normal file
227
usr.sbin/rpc.ypupdated/ypupdated_server.c
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
/*-
|
||||
* 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 server implementation
|
||||
*
|
||||
* Written by Bill Paul <wpaul@ctr.columbia.edu>
|
||||
* Center for Telecommunications Research
|
||||
* Columbia University, New York City
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <stdio.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/key_prot.h>
|
||||
#include <sys/param.h>
|
||||
#include <rpcsvc/yp.h>
|
||||
#include "ypupdate_prot.h"
|
||||
#include "ypupdated_extern.h"
|
||||
#include "yp_extern.h"
|
||||
#include "ypxfr_extern.h"
|
||||
|
||||
int children = 0;
|
||||
int forked = 0;
|
||||
|
||||
/*
|
||||
* Try to avoid spoofing: if a client chooses to use a very large
|
||||
* window and then tries a bunch of randomly chosen encrypted timestamps,
|
||||
* there's a chance he might stumble onto a valid combination.
|
||||
* We therefore reject any RPCs with a window size larger than a preset
|
||||
* value.
|
||||
*/
|
||||
#ifndef WINDOW
|
||||
#define WINDOW (60*60)
|
||||
#endif
|
||||
|
||||
static enum auth_stat
|
||||
yp_checkauth(struct svc_req *svcreq)
|
||||
{
|
||||
struct authdes_cred *des_cred;
|
||||
|
||||
switch (svcreq->rq_cred.oa_flavor) {
|
||||
case AUTH_DES:
|
||||
des_cred = (struct authdes_cred *) svcreq->rq_clntcred;
|
||||
if (des_cred->adc_fullname.window > WINDOW) {
|
||||
yp_error("warning: client-specified window size \
|
||||
was too large -- possible spoof attempt");
|
||||
return(AUTH_BADCRED);
|
||||
}
|
||||
return(AUTH_OK);
|
||||
break;
|
||||
case AUTH_UNIX:
|
||||
case AUTH_NONE:
|
||||
yp_error("warning: client didn't use DES authentication");
|
||||
return(AUTH_TOOWEAK);
|
||||
break;
|
||||
default:
|
||||
yp_error("client used unknown auth flavor");
|
||||
return(AUTH_REJECTEDCRED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int *
|
||||
ypu_change_1_svc(struct ypupdate_args *args, struct svc_req *svcreq)
|
||||
{
|
||||
struct authdes_cred *des_cred;
|
||||
static int res;
|
||||
char *netname;
|
||||
enum auth_stat astat;
|
||||
|
||||
res = 0;
|
||||
|
||||
astat = yp_checkauth(svcreq);
|
||||
|
||||
if (astat != AUTH_OK) {
|
||||
svcerr_auth(svcreq->rq_xprt, astat);
|
||||
return(&res);
|
||||
}
|
||||
|
||||
des_cred = (struct authdes_cred *) svcreq->rq_clntcred;
|
||||
netname = des_cred->adc_fullname.name;
|
||||
|
||||
res = localupdate(netname, "/etc/publickey", YPOP_CHANGE,
|
||||
args->key.yp_buf_len, args->key.yp_buf_val,
|
||||
args->datum.yp_buf_len, args->datum.yp_buf_val);
|
||||
|
||||
if (res)
|
||||
return (&res);
|
||||
|
||||
res = ypmap_update(netname, args->mapname, YPOP_CHANGE,
|
||||
args->key.yp_buf_len, args->key.yp_buf_val,
|
||||
args->datum.yp_buf_len, args->datum.yp_buf_val);
|
||||
|
||||
return (&res);
|
||||
}
|
||||
|
||||
unsigned int *
|
||||
ypu_insert_1_svc(struct ypupdate_args *args, struct svc_req *svcreq)
|
||||
{
|
||||
struct authdes_cred *des_cred;
|
||||
static int res;
|
||||
char *netname;
|
||||
enum auth_stat astat;
|
||||
|
||||
res = 0;
|
||||
|
||||
astat = yp_checkauth(svcreq);
|
||||
|
||||
if (astat != AUTH_OK) {
|
||||
svcerr_auth(svcreq->rq_xprt, astat);
|
||||
return(&res);
|
||||
}
|
||||
|
||||
des_cred = (struct authdes_cred *) svcreq->rq_clntcred;
|
||||
netname = des_cred->adc_fullname.name;
|
||||
|
||||
res = localupdate(netname, "/etc/publickey", YPOP_INSERT,
|
||||
args->key.yp_buf_len, args->key.yp_buf_val,
|
||||
args->datum.yp_buf_len, args->datum.yp_buf_val);
|
||||
|
||||
if (res)
|
||||
return (&res);
|
||||
|
||||
res = ypmap_update(netname, args->mapname, YPOP_INSERT,
|
||||
args->key.yp_buf_len, args->key.yp_buf_val,
|
||||
args->datum.yp_buf_len, args->datum.yp_buf_val);
|
||||
|
||||
return (&res);
|
||||
}
|
||||
|
||||
unsigned int *
|
||||
ypu_delete_1_svc(struct ypdelete_args *args, struct svc_req *svcreq)
|
||||
{
|
||||
struct authdes_cred *des_cred;
|
||||
static int res;
|
||||
char *netname;
|
||||
enum auth_stat astat;
|
||||
|
||||
res = 0;
|
||||
|
||||
astat = yp_checkauth(svcreq);
|
||||
|
||||
if (astat != AUTH_OK) {
|
||||
svcerr_auth(svcreq->rq_xprt, astat);
|
||||
return(&res);
|
||||
}
|
||||
|
||||
des_cred = (struct authdes_cred *) svcreq->rq_clntcred;
|
||||
netname = des_cred->adc_fullname.name;
|
||||
|
||||
res = localupdate(netname, "/etc/publickey", YPOP_DELETE,
|
||||
args->key.yp_buf_len, args->key.yp_buf_val,
|
||||
0, NULL);
|
||||
|
||||
if (res)
|
||||
return (&res);
|
||||
|
||||
res = ypmap_update(netname, args->mapname, YPOP_DELETE,
|
||||
args->key.yp_buf_len, args->key.yp_buf_val,
|
||||
0, NULL);
|
||||
|
||||
return (&res);
|
||||
}
|
||||
|
||||
unsigned int *
|
||||
ypu_store_1_svc(struct ypupdate_args *args, struct svc_req *svcreq)
|
||||
{
|
||||
struct authdes_cred *des_cred;
|
||||
static int res;
|
||||
char *netname;
|
||||
enum auth_stat astat;
|
||||
|
||||
res = 0;
|
||||
|
||||
astat = yp_checkauth(svcreq);
|
||||
|
||||
if (astat != AUTH_OK) {
|
||||
svcerr_auth(svcreq->rq_xprt, astat);
|
||||
return(&res);
|
||||
}
|
||||
|
||||
des_cred = (struct authdes_cred *) svcreq->rq_clntcred;
|
||||
netname = des_cred->adc_fullname.name;
|
||||
|
||||
res = localupdate(netname, "/etc/publickey", YPOP_STORE,
|
||||
args->key.yp_buf_len, args->key.yp_buf_val,
|
||||
args->datum.yp_buf_len, args->datum.yp_buf_val);
|
||||
|
||||
if (res)
|
||||
return (&res);
|
||||
|
||||
res = ypmap_update(netname, args->mapname, YPOP_STORE,
|
||||
args->key.yp_buf_len, args->key.yp_buf_val,
|
||||
args->datum.yp_buf_len, args->datum.yp_buf_val);
|
||||
|
||||
return (&res);
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue