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; }
static bool_t xdr_my_xfr(register XDR *xdrs, xfr *objp) { unsigned char buf[XFRBLOCKSIZE]; while (1) { if ((objp->xfr_u.xfrblock_buf.xfrblock_buf_len = read(fp, &buf, XFRBLOCKSIZE)) != -1) { objp->ok = TRUE; objp->xfr_u.xfrblock_buf.xfrblock_buf_val = (char *)&buf; } else { objp->ok = FALSE; objp->xfr_u.xfrstat = XFR_READ_ERR; yp_error("read error: %s", strerror(errno)); } /* Serialize */ if (!xdr_xfr(xdrs, objp)) return(FALSE); if (objp->ok == FALSE) return(TRUE); if (objp->xfr_u.xfrblock_buf.xfrblock_buf_len < XFRBLOCKSIZE) { objp->ok = FALSE; objp->xfr_u.xfrstat = XFR_DONE; if (!xdr_xfr(xdrs, objp)) return(FALSE); return(TRUE); } } }
int ypxfrd_get_map(char *host, char *map, char *domain, char *tmpname) { CLIENT *clnt; struct ypxfr_mapname req; struct xfr resp; struct timeval timeout = { 0, 25 }; int status = 0; req.xfrmap = map; req.xfrdomain = domain; req.xfrmap_filename = ""; req.xfr_db_type = XFR_DB_BSD_HASH; /* req.xfr_byte_order = XFR_ENDIAN_ANY; * Berkeley DB isn't * byte-order sensitive. */ bzero((char *)&resp, sizeof(resp)); if ((clnt = clnt_create(host, YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS, "tcp")) == NULL) { return(1); } if ((fp = open(tmpname, O_RDWR|O_CREAT, PERM_SECURE)) == -1) { clnt_destroy(clnt); yp_error("couldn't open %s: %s", tmpname, strerror(errno)); return(1); } if (clnt_call(clnt,YPXFRD_GETMAP, (xdrproc_t)xdr_ypxfr_mapname, (char *)&req, (xdrproc_t)xdr_my_xfr, (char *)&resp, timeout) != RPC_SUCCESS) { yp_error("%s", clnt_sperror(clnt,"call to rpc.ypxfrd failed")); status++; unlink(tmpname); } clnt_destroy(clnt); close(fp); return(status); }
static void ypxfr_exit(ypxfrstat retval, char *temp) { CLIENT *clnt; int sock = RPC_ANYSOCK; struct timeval timeout; /* Clean up no matter what happened previously. */ if (temp != NULL) { if (dbp != NULL) (void)(dbp->close)(dbp); if (unlink(temp) == -1) { yp_error("failed to unlink %s",strerror(errno)); } } if (ypxfr_prognum) { timeout.tv_sec = 20; timeout.tv_usec = 0; if ((clnt = clntudp_create(&ypxfr_callback_addr, ypxfr_prognum, 1, timeout, &sock)) == NULL) { yp_error("%s", clnt_spcreateerror("failed to " "establish callback handle")); exit(1); } ypxfr_resp.status = (yppush_status)retval; if (yppushproc_xfrresp_1(&ypxfr_resp, clnt) == NULL) { yp_error("%s", clnt_sperror(clnt, "callback failed")); clnt_destroy(clnt); exit(1); } clnt_destroy(clnt); } else { yp_error("Exiting: %s", ypxfrerr_string(retval)); } exit(0); }
static int validchars(char *arg) { size_t i; for (i = 0; i < strlen(arg); i++) { if (iscntrl(arg[i])) { yp_error("string contains a control character"); return(1); } if (arg[i] == ':') { yp_error("string contains a colon"); return(1); } /* Be evil: truncate strings with \n in them silently. */ if (arg[i] == '\n') { arg[i] = '\0'; return(0); } } return(0); }
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); }
static bool_t xdr_my_xfr(register XDR *xdrs, xfr *objp) { while (1) { if (!xdr_xfr(xdrs, objp)) return(FALSE); if (objp->ok == TRUE) { if (write(fp, objp->xfr_u.xfrblock_buf.xfrblock_buf_val, objp->xfr_u.xfrblock_buf.xfrblock_buf_len) == -1) { yp_error("write failed: %s", strerror(errno)); return(FALSE); } } xdr_free((xdrproc_t)xdr_xfr, (char *)objp); if (objp->ok == FALSE) { switch (objp->xfr_u.xfrstat) { case(XFR_DONE): return(TRUE); break; case(XFR_READ_ERR): yp_error("got read error from rpc.ypxfrd"); return(FALSE); break; case(XFR_ACCESS): yp_error("rpc.ypxfrd couldn't access the map"); return(FALSE); break; case(XFR_DENIED): yp_error("access to map denied by rpc.ypxfrd"); return(FALSE); break; case(XFR_DB_TYPE_MISMATCH): yp_error("client/server DB type mismatch"); return(FALSE); break; case(XFR_DB_ENDIAN_MISMATCH): yp_error("client/server byte order mismatch"); return(FALSE); break; default: yp_error("got unknown status from rpc.ypxfrd"); return(FALSE); break; } } } }
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 */ }
int main(int argc, char *argv[]) { int ch; int ypxfr_force = 0; char *ypxfr_dest_domain = NULL; char *ypxfr_source_host = NULL; char *ypxfr_source_domain = NULL; char *ypxfr_local_domain = NULL; char *ypxfr_master = NULL; unsigned long ypxfr_order = -1, ypxfr_skew_check = -1; char *ypxfr_mapname = NULL; int ypxfr_args = 0; char ypxfr_temp_map[MAXPATHLEN + 2]; char tempmap[MAXPATHLEN + 2]; char buf[MAXPATHLEN + 2]; DBT key, data; int remoteport; int interdom = 0; int secure = 0; debug = 1; if (!isatty(fileno(stderr))) { openlog("ypxfr", LOG_PID, LOG_DAEMON); _rpcpmstart = 1; } if (argc < 2) usage(); while ((ch = getopt(argc, argv, "fcd:h:s:p:C:")) != -1) { int my_optind; switch (ch) { case 'f': ypxfr_force++; ypxfr_args++; break; case 'c': ypxfr_clear = 0; ypxfr_args++; break; case 'd': ypxfr_dest_domain = optarg; ypxfr_args += 2; break; case 'h': ypxfr_source_host = optarg; ypxfr_args += 2; break; case 's': ypxfr_source_domain = optarg; ypxfr_args += 2; break; case 'p': yp_dir = optarg; ypxfr_args += 2; break; case 'C': /* * Whoever decided that the -C flag should take * four arguments is a twit. */ my_optind = optind - 1; if (argv[my_optind] == NULL || !strlen(argv[my_optind])) { yp_error("transaction ID not specified"); usage(); } ypxfr_resp.transid = atol(argv[my_optind]); my_optind++; if (argv[my_optind] == NULL || !strlen(argv[my_optind])) { yp_error("RPC program number not specified"); usage(); } ypxfr_prognum = atol(argv[my_optind]); my_optind++; if (argv[my_optind] == NULL || !strlen(argv[my_optind])) { yp_error("address not specified"); usage(); } if (!inet_aton(argv[my_optind], &ypxfr_callback_addr.sin_addr)) { yp_error("failed to convert '%s' to IP addr", argv[my_optind]); exit(1); } my_optind++; if (argv[my_optind] == NULL || !strlen(argv[my_optind])) { yp_error("port not specified"); usage(); } ypxfr_callback_addr.sin_port = htons((u_short)atoi(argv[my_optind])); ypxfr_args += 5; break; default: usage(); break; } } ypxfr_mapname = argv[ypxfr_args + 1]; if (ypxfr_mapname == NULL) { yp_error("no map name specified"); usage(); } /* Always the case. */ ypxfr_callback_addr.sin_family = AF_INET; /* Determine if local NIS client facilities are turned on. */ if (!yp_get_default_domain(&ypxfr_local_domain) && _yp_check(&ypxfr_local_domain)) ypxfr_use_yplib = 1; /* * If no destination domain is specified, assume that the * local default domain is to be used and try to obtain it. * Fails if NIS client facilities are turned off. */ if (ypxfr_dest_domain == NULL) { if (ypxfr_use_yplib) { yp_get_default_domain(&ypxfr_dest_domain); } else { yp_error("no destination domain specified and \ the local domain name isn't set"); ypxfr_exit(YPXFR_BADARGS,NULL); } } /* * If a source domain is not specified, assume it to * be the same as the destination domain. */ if (ypxfr_source_domain == NULL) { ypxfr_source_domain = ypxfr_dest_domain; } /* * If the source host is not specified, assume it to be the * master for the specified map. If local NIS client facilities * are turned on, we can figure this out using yp_master(). * If not, we have to see if a local copy of the map exists * and extract its YP_MASTER_NAME record. If _that_ fails, * we are stuck and must ask the user for more information. */ if (ypxfr_source_host == NULL) { if (!ypxfr_use_yplib) { /* * Double whammy: NIS isn't turned on and the user * didn't specify a source host. */ char *dptr; key.data = "YP_MASTER_NAME"; key.size = sizeof("YP_MASTER_NAME") - 1; if (yp_get_record(ypxfr_dest_domain, ypxfr_mapname, &key, &data, 1) != YP_TRUE) { yp_error("no source host specified"); ypxfr_exit(YPXFR_BADARGS,NULL); } dptr = data.data; dptr[data.size] = '\0'; ypxfr_master = ypxfr_source_host = strdup(dptr); } } else { if (ypxfr_use_yplib) ypxfr_use_yplib = 0; } if (ypxfr_master == NULL) { if ((ypxfr_master = ypxfr_get_master(ypxfr_source_domain, ypxfr_mapname, ypxfr_source_host, ypxfr_use_yplib)) == NULL) { yp_error("failed to find master of %s in domain %s: %s", ypxfr_mapname, ypxfr_source_domain, ypxfrerr_string((ypxfrstat)yp_errno)); ypxfr_exit(YPXFR_MADDR,NULL); } } /* * If we got here and ypxfr_source_host is still undefined, * it means we had to resort to using yp_master() to find the * master server for the map. The source host and master should * be identical. */ if (ypxfr_source_host == NULL) ypxfr_source_host = ypxfr_master; /* * Don't talk to ypservs on unprivileged ports. */ remoteport = getrpcport(ypxfr_source_host, YPPROG, YPVERS, IPPROTO_UDP); if (remoteport >= IPPORT_RESERVED) { yp_error("ypserv on %s not running on reserved port", ypxfr_source_host); ypxfr_exit(YPXFR_REFUSED, NULL); } if ((ypxfr_order = ypxfr_get_order(ypxfr_source_domain, ypxfr_mapname, ypxfr_master, 0)) == 0) { yp_error("failed to get order number of %s: %s", ypxfr_mapname, yp_errno == YP_TRUE ? "map has order 0" : ypxfrerr_string((ypxfrstat)yp_errno)); ypxfr_exit(YPXFR_YPERR,NULL); } if (ypxfr_match(ypxfr_master, ypxfr_source_domain, ypxfr_mapname, "YP_INTERDOMAIN", sizeof("YP_INTERDOMAIN") - 1)) interdom++; if (ypxfr_match(ypxfr_master, ypxfr_source_domain, ypxfr_mapname, "YP_SECURE", sizeof("YP_SECURE") - 1)) secure++; key.data = "YP_LAST_MODIFIED"; key.size = sizeof("YP_LAST_MODIFIED") - 1; /* The order number is immaterial when the 'force' flag is set. */ if (!ypxfr_force) { int ignore = 0; if (yp_get_record(ypxfr_dest_domain,ypxfr_mapname,&key,&data,1) != YP_TRUE) { switch (yp_errno) { case YP_NOKEY: ypxfr_exit(YPXFR_FORCE,NULL); break; case YP_NOMAP: /* * If the map doesn't exist, we're * creating it. Ignore the error. */ ignore++; break; case YP_BADDB: default: ypxfr_exit(YPXFR_DBM,NULL); break; } } if (!ignore && ypxfr_order <= atoi(data.data)) ypxfr_exit(YPXFR_AGE, NULL); } /* Construct a temporary map file name */ snprintf(tempmap, sizeof(tempmap), "%s.%d",ypxfr_mapname, getpid()); snprintf(ypxfr_temp_map, sizeof(ypxfr_temp_map), "%s/%s/%s", yp_dir, ypxfr_dest_domain, tempmap); if ((remoteport = getrpcport(ypxfr_source_host, YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS, IPPROTO_TCP))) { /* Don't talk to rpc.ypxfrds on unprovileged ports. */ if (remoteport >= IPPORT_RESERVED) { yp_error("rpc.ypxfrd on %s not using privileged port", ypxfr_source_host); ypxfr_exit(YPXFR_REFUSED, NULL); } /* Try to send using ypxfrd. If it fails, use old method. */ if (!ypxfrd_get_map(ypxfr_source_host, ypxfr_mapname, ypxfr_source_domain, ypxfr_temp_map)) goto leave; } /* Open the temporary map read/write. */ if ((dbp = yp_open_db_rw(ypxfr_dest_domain, tempmap, 0)) == NULL) { yp_error("failed to open temporary map file"); ypxfr_exit(YPXFR_DBM,NULL); } /* * Fill in the keys we already know, such as the order number, * master name, input file name (we actually make up a bogus * name for that) and output file name. */ snprintf(buf, sizeof(buf), "%lu", ypxfr_order); data.data = buf; data.size = strlen(buf); if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to write order number to database"); ypxfr_exit(YPXFR_DBM,ypxfr_temp_map); } key.data = "YP_MASTER_NAME"; key.size = sizeof("YP_MASTER_NAME") - 1; data.data = ypxfr_master; data.size = strlen(ypxfr_master); if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to write master name to database"); ypxfr_exit(YPXFR_DBM,ypxfr_temp_map); } key.data = "YP_DOMAIN_NAME"; key.size = sizeof("YP_DOMAIN_NAME") - 1; data.data = ypxfr_dest_domain; data.size = strlen(ypxfr_dest_domain); if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to write domain name to database"); ypxfr_exit(YPXFR_DBM,ypxfr_temp_map); } snprintf (buf, sizeof(buf), "%s:%s", ypxfr_source_host, ypxfr_mapname); key.data = "YP_INPUT_NAME"; key.size = sizeof("YP_INPUT_NAME") - 1; data.data = &buf; data.size = strlen(buf); if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to write input name to database"); ypxfr_exit(YPXFR_DBM,ypxfr_temp_map); } snprintf(buf, sizeof(buf), "%s/%s/%s", yp_dir, ypxfr_dest_domain, ypxfr_mapname); key.data = "YP_OUTPUT_NAME"; key.size = sizeof("YP_OUTPUT_NAME") - 1; data.data = &buf; data.size = strlen(buf); if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to write output name to database"); ypxfr_exit(YPXFR_DBM,ypxfr_temp_map); } if (interdom) { key.data = "YP_INTERDOMAIN"; key.size = sizeof("YP_INTERDOMAIN") - 1; data.data = ""; data.size = 0; if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to add interdomain flag to database"); ypxfr_exit(YPXFR_DBM,ypxfr_temp_map); } } if (secure) { key.data = "YP_SECURE"; key.size = sizeof("YP_SECURE") - 1; data.data = ""; data.size = 0; if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to add secure flag to database"); ypxfr_exit(YPXFR_DBM,ypxfr_temp_map); } } /* Now suck over the contents of the map from the master. */ if (ypxfr_get_map(ypxfr_mapname,ypxfr_source_domain, ypxfr_source_host, ypxfr_foreach)){ yp_error("failed to retrieve map from source host"); ypxfr_exit(YPXFR_YPERR,ypxfr_temp_map); } (void)(dbp->close)(dbp); dbp = NULL; /* <- yes, it seems this is necessary. */ leave: snprintf(buf, sizeof(buf), "%s/%s/%s", yp_dir, ypxfr_dest_domain, ypxfr_mapname); /* Peek at the order number again and check for skew. */ if ((ypxfr_skew_check = ypxfr_get_order(ypxfr_source_domain, ypxfr_mapname, ypxfr_master, 0)) == 0) { yp_error("failed to get order number of %s: %s", ypxfr_mapname, yp_errno == YP_TRUE ? "map has order 0" : ypxfrerr_string((ypxfrstat)yp_errno)); ypxfr_exit(YPXFR_YPERR,ypxfr_temp_map); } if (ypxfr_order != ypxfr_skew_check) ypxfr_exit(YPXFR_SKEW,ypxfr_temp_map); /* * Send a YPPROC_CLEAR to the local ypserv. */ if (ypxfr_clear) { char in = 0; char *out = NULL; int stat; if ((stat = callrpc("localhost",YPPROG,YPVERS,YPPROC_CLEAR, (xdrproc_t)xdr_void, (void *)&in, (xdrproc_t)xdr_void, (void *)out)) != RPC_SUCCESS) { yp_error("failed to send 'clear' to local ypserv: %s", clnt_sperrno((enum clnt_stat) stat)); ypxfr_exit(YPXFR_CLEAR, ypxfr_temp_map); } } /* * Put the new map in place immediately. I'm not sure if the * kernel does an unlink() and rename() atomically in the event * that we move a new copy of a map over the top of an existing * one, but there's less chance of a race condition happening * than if we were to do the unlink() ourselves. */ if (rename(ypxfr_temp_map, buf) == -1) { yp_error("rename(%s,%s) failed: %s", ypxfr_temp_map, buf, strerror(errno)); ypxfr_exit(YPXFR_FILE,NULL); } ypxfr_exit(YPXFR_SUCC,NULL); return(1); }
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[YPMAXRECORD]; 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)); }