/* * Create the client des authentication object. Obsoleted by * authdes_seccreate(). */ AUTH * authdes_create(char *servername, uint_t window, struct sockaddr_in *syncaddr, des_block *ckey) { char *hostname = NULL; if (syncaddr) { /* * Change addr to hostname, because that is the way * new interface takes it. */ struct netconfig *nconf; struct netbuf nb_syncaddr; struct nd_hostservlist *hlist; AUTH *nauth; int fd; struct t_info tinfo; if ((nconf = __rpc_getconfip("udp")) == NULL && (nconf = __rpc_getconfip("tcp")) == NULL) goto fallback; /* Transform sockaddr_in to netbuf */ if ((fd = t_open(nconf->nc_device, O_RDWR, &tinfo)) == -1) { (void) freenetconfigent(nconf); goto fallback; } (void) t_close(fd); nb_syncaddr.maxlen = nb_syncaddr.len = __rpc_get_a_size(tinfo.addr); nb_syncaddr.buf = (char *)syncaddr; if (netdir_getbyaddr(nconf, &hlist, &nb_syncaddr)) { (void) freenetconfigent(nconf); goto fallback; } if (hlist && hlist->h_cnt > 0 && hlist->h_hostservs) hostname = hlist->h_hostservs->h_host; nauth = authdes_seccreate(servername, window, hostname, ckey); (void) netdir_free((char *)hlist, ND_HOSTSERVLIST); (void) freenetconfigent(nconf); return (nauth); } fallback: return (authdes_seccreate(servername, window, hostname, ckey)); }
/* * __yp_all_cflookup() is a variant of the yp_all() code, * which adds a 'hardlookup' parameter. This parameter is passed * to __yp_dobind_cflookup(), and determines whether the server * binding attempt is hard (try forever) of soft (retry a compiled- * in number of times). */ int __yp_all_cflookup(char *domain, char *map, struct ypall_callback *callback, int hardlookup) { size_t domlen; size_t maplen; struct ypreq_nokey req; int reason; struct dom_binding *pdomb; enum clnt_stat s; CLIENT *allc; char server_name[MAXHOSTNAMELEN]; char errbuf[BUFSIZ]; if ((map == NULL) || (domain == NULL)) return (YPERR_BADARGS); domlen = strlen(domain); maplen = strlen(map); if ((domlen == 0) || (domlen > YPMAXDOMAIN) || (maplen == 0) || (maplen > YPMAXMAP) || (callback == NULL)) return (YPERR_BADARGS); if (reason = __yp_dobind_cflookup(domain, &pdomb, hardlookup)) return (reason); if (pdomb->dom_binding->ypbind_hi_vers < YPVERS) { __yp_rel_binding(pdomb); return (YPERR_VERS); } (void) mutex_lock(&pdomb->server_name_lock); if (!pdomb->dom_binding->ypbind_servername) { (void) mutex_unlock(&pdomb->server_name_lock); __yp_rel_binding(pdomb); syslog(LOG_ERR, "yp_all: failed to get server's name\n"); return (YPERR_RPC); } (void) strcpy(server_name, pdomb->dom_binding->ypbind_servername); (void) mutex_unlock(&pdomb->server_name_lock); if (strcmp(server_name, nullstring) == 0) { /* * This is the case where ypbind is running in broadcast mode, * we have to do the jugglery to get the * ypserv's address on COTS transport based * on the CLTS address ypbind gave us ! */ struct nd_hostservlist *nhs; if (netdir_getbyaddr(pdomb->dom_binding->ypbind_nconf, &nhs, pdomb->dom_binding->ypbind_svcaddr) != ND_OK) { syslog(LOG_ERR, "yp_all: failed to get server's name\n"); __yp_rel_binding(pdomb); return (YPERR_RPC); } /* check server name again, some other thread may have set it */ (void) mutex_lock(&pdomb->server_name_lock); if (strcmp(pdomb->dom_binding->ypbind_servername, nullstring) == 0) { pdomb->dom_binding->ypbind_servername = (char *)strdup(nhs->h_hostservs->h_host); } (void) strcpy(server_name, pdomb->dom_binding->ypbind_servername); (void) mutex_unlock(&pdomb->server_name_lock); netdir_free((char *)nhs, ND_HOSTSERVLIST); } __yp_rel_binding(pdomb); if ((allc = clnt_create(server_name, YPPROG, YPVERS, "circuit_n")) == NULL) { (void) snprintf(errbuf, BUFSIZ, "yp_all \ - transport level create failure for domain %s / map %s", domain, map); syslog(LOG_ERR, "%s", clnt_spcreateerror(errbuf)); return (YPERR_RPC); }
/* * Called to read and interpret the event on a connectionless descriptor. * Returns 0 if successful, or a UNIX error code if failure. */ static int do_poll_clts_action(int fd, int conn_index) { int error; int ret; int flags; struct netconfig *nconf = &conn_polled[conn_index].nc; static struct t_unitdata *unitdata = NULL; static struct t_uderr *uderr = NULL; static int oldfd = -1; struct nd_hostservlist *host = NULL; struct strbuf ctl[1], data[1]; /* * We just need to have some space to consume the * message in the event we can't use the TLI interface to do the * job. * * We flush the message using getmsg(). For the control part * we allocate enough for any TPI header plus 32 bytes for address * and options. For the data part, there is nothing magic about * the size of the array, but 256 bytes is probably better than * 1 byte, and we don't expect any data portion anyway. * * If the array sizes are too small, we handle this because getmsg() * (called to consume the message) will return MOREDATA|MORECTL. * Thus we just call getmsg() until it's read the message. */ char ctlbuf[sizeof (union T_primitives) + 32]; char databuf[256]; /* * If this is the same descriptor as the last time * do_poll_clts_action was called, we can save some * de-allocation and allocation. */ if (oldfd != fd) { oldfd = fd; if (unitdata) { (void) t_free((char *)unitdata, T_UNITDATA); unitdata = NULL; } if (uderr) { (void) t_free((char *)uderr, T_UDERROR); uderr = NULL; } } /* * Allocate a unitdata structure for receiving the event. */ if (unitdata == NULL) { /* LINTED pointer alignment */ unitdata = (struct t_unitdata *)t_alloc(fd, T_UNITDATA, T_ALL); if (unitdata == NULL) { if (t_errno == TSYSERR) { /* * Save the error code across * syslog(), just in case * syslog() gets its own error * and therefore overwrites errno. */ error = errno; (void) syslog(LOG_ERR, "t_alloc(file descriptor %d/transport %s, T_UNITDATA) failed: %m", fd, nconf->nc_proto); return (error); } (void) syslog(LOG_ERR, "t_alloc(file descriptor %d/transport %s, T_UNITDATA) failed TLI error %d", fd, nconf->nc_proto, t_errno); goto flush_it; } } try_again: flags = 0; /* * The idea is we wait for T_UNITDATA_IND's. Of course, * we don't get any, because rpcmod filters them out. * However, we need to call t_rcvudata() to let TLI * tell us we have a T_UDERROR_IND. * * algorithm is: * t_rcvudata(), expecting TLOOK. * t_look(), expecting T_UDERR. * t_rcvuderr(), expecting success (0). * expand destination address into ASCII, * and dump it. */ ret = t_rcvudata(fd, unitdata, &flags); if (ret == 0 || t_errno == TBUFOVFLW) { (void) syslog(LOG_WARNING, "t_rcvudata(file descriptor %d/transport %s) got unexpected data, %d bytes", fd, nconf->nc_proto, unitdata->udata.len); /* * Even though we don't expect any data, in case we do, * keep reading until there is no more. */ if (flags & T_MORE) goto try_again; return (0); } switch (t_errno) { case TNODATA: return (0); case TSYSERR: /* * System errors are returned to caller. * Save the error code across * syslog(), just in case * syslog() gets its own error * and therefore overwrites errno. */ error = errno; (void) syslog(LOG_ERR, "t_rcvudata(file descriptor %d/transport %s) %m", fd, nconf->nc_proto); return (error); case TLOOK: break; default: (void) syslog(LOG_ERR, "t_rcvudata(file descriptor %d/transport %s) TLI error %d", fd, nconf->nc_proto, t_errno); goto flush_it; } ret = t_look(fd); switch (ret) { case 0: return (0); case -1: /* * System errors are returned to caller. */ if (t_errno == TSYSERR) { /* * Save the error code across * syslog(), just in case * syslog() gets its own error * and therefore overwrites errno. */ error = errno; (void) syslog(LOG_ERR, "t_look(file descriptor %d/transport %s) %m", fd, nconf->nc_proto); return (error); } (void) syslog(LOG_ERR, "t_look(file descriptor %d/transport %s) TLI error %d", fd, nconf->nc_proto, t_errno); goto flush_it; case T_UDERR: break; default: (void) syslog(LOG_WARNING, "t_look(file descriptor %d/transport %s) returned %d not T_UDERR (%d)", fd, nconf->nc_proto, ret, T_UDERR); } if (uderr == NULL) { /* LINTED pointer alignment */ uderr = (struct t_uderr *)t_alloc(fd, T_UDERROR, T_ALL); if (uderr == NULL) { if (t_errno == TSYSERR) { /* * Save the error code across * syslog(), just in case * syslog() gets its own error * and therefore overwrites errno. */ error = errno; (void) syslog(LOG_ERR, "t_alloc(file descriptor %d/transport %s, T_UDERROR) failed: %m", fd, nconf->nc_proto); return (error); } (void) syslog(LOG_ERR, "t_alloc(file descriptor %d/transport %s, T_UDERROR) failed TLI error: %d", fd, nconf->nc_proto, t_errno); goto flush_it; } } ret = t_rcvuderr(fd, uderr); if (ret == 0) { /* * Save the datagram error in errno, so that the * %m argument to syslog picks up the error string. */ errno = uderr->error; /* * Log the datagram error, then log the host that * probably triggerred. Cannot log both in the * same transaction because of packet size limitations * in /dev/log. */ (void) syslog((errno == ECONNREFUSED) ? LOG_DEBUG : LOG_WARNING, "NFS response over <file descriptor %d/transport %s> generated error: %m", fd, nconf->nc_proto); /* * Try to map the client's address back to a * name. */ ret = netdir_getbyaddr(nconf, &host, &uderr->addr); if (ret != -1 && host && host->h_cnt > 0 && host->h_hostservs) { (void) syslog((errno == ECONNREFUSED) ? LOG_DEBUG : LOG_WARNING, "Bad NFS response was sent to client with host name: %s; service port: %s", host->h_hostservs->h_host, host->h_hostservs->h_serv); } else { int i, j; char *buf; char *hex = "0123456789abcdef"; /* * Mapping failed, print the whole thing * in ASCII hex. */ buf = (char *)malloc(uderr->addr.len * 2 + 1); for (i = 0, j = 0; i < uderr->addr.len; i++, j += 2) { buf[j] = hex[((uderr->addr.buf[i]) >> 4) & 0xf]; buf[j+1] = hex[uderr->addr.buf[i] & 0xf]; } buf[j] = '\0'; (void) syslog((errno == ECONNREFUSED) ? LOG_DEBUG : LOG_WARNING, "Bad NFS response was sent to client with transport address: 0x%s", buf); free((void *)buf); } if (ret == 0 && host != NULL) netdir_free((void *)host, ND_HOSTSERVLIST); return (0); }
static void nfsauth_access(auth_req *argp, auth_res *result) { struct netconfig *nconf; struct nd_hostservlist *clnames = NULL; struct netbuf nbuf; struct share *sh; char tmp[MAXIPADDRLEN]; char *host = NULL; result->auth_perm = NFSAUTH_DENIED; /* * Convert the client's address to a hostname */ nconf = getnetconfigent(argp->req_netid); if (nconf == NULL) { syslog(LOG_ERR, "No netconfig entry for %s", argp->req_netid); return; } nbuf.len = argp->req_client.n_len; nbuf.buf = argp->req_client.n_bytes; if (netdir_getbyaddr(nconf, &clnames, &nbuf)) { host = &tmp[0]; if (strcmp(nconf->nc_protofmly, NC_INET) == 0) { struct sockaddr_in *sa; /* LINTED pointer alignment */ sa = (struct sockaddr_in *)nbuf.buf; (void) inet_ntoa_r(sa->sin_addr, tmp); } else if (strcmp(nconf->nc_protofmly, NC_INET6) == 0) { struct sockaddr_in6 *sa; /* LINTED pointer */ sa = (struct sockaddr_in6 *)nbuf.buf; (void) inet_ntop(AF_INET6, sa->sin6_addr.s6_addr, tmp, INET6_ADDRSTRLEN); } clnames = anon_client(host); } /* * Now find the export */ sh = findentry(argp->req_path); if (sh == NULL) { syslog(LOG_ERR, "%s not exported", argp->req_path); goto done; } result->auth_perm = check_client(sh, &nbuf, clnames, argp->req_flavor); sharefree(sh); if (result->auth_perm == NFSAUTH_DENIED) { syslog(LOG_ERR, "%s denied access to %s", clnames->h_hostservs[0].h_host, argp->req_path); } done: freenetconfigent(nconf); if (clnames) netdir_free(clnames, ND_HOSTSERVLIST); }