/* * Revoke the authentication key in the given AUTH handle by setting * it to NULL. If newkey is true, then generate a new key instead of * nulling out the old one. This is necessary for AUTH_DES because * the new key will be used next time the user does a keylogin. If * the zero'd key is used as actual key, then it cannot be revoked * again! */ void revoke_key(AUTH *auth, int newkey) { if (auth == NULL) return; if (newkey) { if (key_gendes(&auth->ah_key) != RPC_SUCCESS) { /* failed to get new key, munge the old one */ auth->ah_key.key.high ^= auth->ah_key.key.low; auth->ah_key.key.low += auth->ah_key.key.high; } } else { /* null out old key */ auth->ah_key.key.high = 0; auth->ah_key.key.low = 0; } }
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); }
/* * 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); }
AUTH * authdes_pk_create (const char *servername, netobj *pkey, u_int window, struct sockaddr *syncaddr, des_block *ckey) { AUTH *auth; struct ad_private *ad; char namebuf[MAXNETNAMELEN + 1]; /* * Allocate everything now */ auth = ALLOC (AUTH); ad = ALLOC (struct ad_private); if (auth == NULL || ad == NULL) { debug ("authdes_create: out of memory"); goto failed; } memset (ad, 0, sizeof (struct ad_private)); memcpy (ad->ad_pkey, pkey->n_bytes, pkey->n_len); if (!getnetname (namebuf)) goto failed; ad->ad_fullnamelen = RNDUP (strlen (namebuf)); ad->ad_fullname = mem_alloc (ad->ad_fullnamelen + 1); ad->ad_servernamelen = strlen (servername); ad->ad_servername = mem_alloc (ad->ad_servernamelen + 1); if (ad->ad_fullname == NULL || ad->ad_servername == NULL) { debug ("authdes_create: out of memory"); goto failed; } /* * Set up private data */ memcpy (ad->ad_fullname, namebuf, ad->ad_fullnamelen + 1); memcpy (ad->ad_servername, servername, ad->ad_servernamelen + 1); ad->ad_timediff.tv_sec = ad->ad_timediff.tv_usec = 0; if (syncaddr != NULL) { ad->ad_syncaddr = *syncaddr; ad->ad_dosync = TRUE; } else ad->ad_dosync = FALSE; ad->ad_window = window; if (ckey == NULL) { if (key_gendes (&auth->ah_key) < 0) { debug ("authdes_create: unable to gen conversation 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 = (struct auth_ops *) &authdes_ops; auth->ah_private = (caddr_t) ad; if (!authdes_refresh (auth)) goto failed; return auth; failed: if (auth != NULL) FREE (auth, sizeof (AUTH)); if (ad != NULL) { if (ad->ad_fullname != NULL) FREE (ad->ad_fullname, ad->ad_fullnamelen + 1); if (ad->ad_servername != NULL) FREE (ad->ad_servername, ad->ad_servernamelen + 1); FREE (ad, sizeof (struct ad_private)); } return NULL; }