rpc.yppasswdd.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 381 行

C
381
字号
#ifndef lintstatic char *sccsid = "@(#)rpc.yppasswdd.c	4.1      ULTRIX  7/2/90";#endif lint/**************************************************************** *								* *  Licensed to Digital Equipment Corporation, Maynard, MA	* *		Copyright 1985 Sun Microsystems, Inc.		* *			All rights reserved.			* *								* ****************************************************************//*	Revsions *	-------- * * Oct 31, 1989 dal/ Fixed problem handling errors during passwd update * * Apr 20, 1989 jhw/ Fixed security hole * * Jun 12, 1988 jhw/ Fixed username parsing in getpwnam * * Jun 09, 1988 map/ Changed signal handlers to void. * * Jul 30,1986	rjg/ Modified "rename" of temporary passwd file *		so that rpc.yppasswdd would work if the source *		passwd file existed on another file system. *		ie. if  /etc/yp  is a symbolic link to  /usr/etc/yp *		the rename would fail. Can't rename across devices. *		The Sun makefile at installation time creates a *		link  /etc/yp  to  /usr/etc/yp  to save space on *		the root file system. */#include <sys/param.h>#include <sys/errno.h>#include <stdio.h>#include <signal.h>#include <sys/file.h>#include <rpc/rpc.h>#include <pwd.h>#include <rpcsvc/yppasswd.h>#include <errno.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <sys/wait.h>#include <ctype.h>char *file;			/* file in which passwd's are found */char	temp[MAXPATHLEN+1];int mflag;			/* do a make */char *index();int boilerplate();extern int errno;int Argc;char **Argv;main(argc, argv)	char **argv;{	SVCXPRT *transp;	int s;		Argc = argc;	Argv = argv;	if (argc < 2) {	    	fprintf(stderr,"usage: %s file [-m arg1 arg2 ...]\n", argv[0]);		exit(1);	}	file = argv[1];	if (access(file, W_OK) < 0) {		fprintf(stderr, "can't write %s\n", file);		exit(1);	}	if (argc > 2 && argv[2][0] == '-' && argv[2][1] == 'm')		mflag++;			if (chdir("/etc/yp") < 0) {		fprintf(stderr, "yppasswdd: can't chdir to /etc/yp\n");		exit(1);	}	if ((s = rresvport()) < 0) {		fprintf(stderr,		    "yppasswdd: can't bind to a privileged socket\n");		exit(1);	}	transp = svcudp_create(s);	if (transp == NULL) {		fprintf(stderr, "yppasswdd: couldn't create an RPC server\n");		exit(1);	}	pmap_unset(YPPASSWDPROG, YPPASSWDVERS);	if (!svc_register(transp, YPPASSWDPROG, YPPASSWDVERS,	    boilerplate, IPPROTO_UDP)) {		fprintf(stderr, "yppasswdd: couldn't register yppasswdd\n");		exit(1);	}	if (fork())		exit(0);	{ int t;	for (t = getdtablesize()-1; t >= 0; t--)		if (t != s)			(void) close(t);	}	(void) open("/", O_RDONLY);	(void) dup2(0, 1);	(void) dup2(0, 2);	{ int tt = open("/dev/tty", O_RDWR);	  if (tt > 0) {		ioctl(tt, TIOCNOTTY, 0);		close(tt);	  }	}	svc_run();	fprintf(stderr, "yppasswdd: svc_run shouldn't have returned\n");}boilerplate(rqstp, transp)	struct svc_req *rqstp;	SVCXPRT *transp;{	switch(rqstp->rq_proc) {		case NULLPROC:			if (!svc_sendreply(transp, xdr_void, 0))				fprintf(stderr,				    "yppasswdd: couldn't reply to RPC call\n");			break;		case YPPASSWDPROC_UPDATE:			changepasswd(rqstp, transp);			break;	}}changepasswd(rqstp, transp)	struct svc_req *rqstp;	SVCXPRT *transp;{	int tempfd, lockfd, i, len;	static int ans;	FILE *tempfp, *filefp;	char buf[256], *p, *s;	char cmdbuf[BUFSIZ];	void (*f1)(), (*f2)(), (*f3)();	struct passwd *oldpw, *newpw;	struct yppasswd yppasswd;	union wait status;		bzero(&yppasswd, sizeof(yppasswd));	if (!svc_getargs(transp, xdr_yppasswd, &yppasswd)) {		svcerr_decode(transp);		return;	}	/* 	 * Clean up from previous changepasswd() call	 */	while (wait3(&status, WNOHANG, 0) > 0)		continue;	newpw = &yppasswd.newpw;	ans = 1;	oldpw = getpwnam(newpw->pw_name);	if (oldpw == NULL) {		fprintf(stderr, "yppasswdd: no passwd for %s\n",		    newpw->pw_name);		goto done;	}	if (oldpw->pw_passwd && *oldpw->pw_passwd &&	    strcmp(crypt(yppasswd.oldpass,oldpw->pw_passwd),	    oldpw->pw_passwd) != 0) {		fprintf(stderr, "yppasswdd: %s: bad passwd\n", newpw->pw_name);		goto done;	}	(void) umask(022);	f1 = signal(SIGHUP, SIG_IGN);	f2 = signal(SIGINT, SIG_IGN);	f3 = signal(SIGQUIT, SIG_IGN);/* * Make a temporary file name. */	strcpy(temp, file);	if(!strcmp(temp, "/etc/passwd"))		strcpy(temp, "/etc/ptmp");	else		strcat(temp, ".tmp");/* * Lock the map source file. */	tempfd = open(temp, O_WRONLY|O_CREAT|O_EXCL, 0644);	if (tempfd < 0) {		fprintf(stderr, "yppasswdd: ");		if (errno == EEXIST)			fprintf(stderr, "password file busy - try again.\n");		else			perror(temp);		goto cleanup_noclose;	}	signal(SIGTSTP, SIG_IGN);	if ((tempfp = fdopen(tempfd, "w")) == NULL) {		fprintf(stderr, "yppasswdd: fdopen failed?\n");		goto cleanup;	}	/*	 * Copy passwd to temp, replacing matching lines	 * with new password.	 */	if ((filefp = fopen(file, "r")) == NULL) {		fprintf(stderr, "yppasswdd: fopen of %s failed?\n", file);		fclose(tempfp);		goto cleanup;	}	len = strlen(newpw->pw_name);        /*        * This fixes a really bogus security hole, basically anyone can        * call the rpc passwd deamon, give them their own passwd and a        * new one that consists of ':0:0:Im root now:/:/bin/csh^J' and        * give themselves root access. With this code it will simply make        * it impossible for them to login again, and as a bonus leave        * a cookie for the always vigilant system administrator to ferret        * them out.        */        for (p = newpw->pw_passwd; (*p != '\0'); p++)                if ((*p == ':') || !(isprint(*p)))                        *p = '$';       /* you lose buckwheat */                                                                   	while (fgets(buf, sizeof(buf), filefp)) {		p = index(buf, ':');		if (p && p - buf == len		    && strncmp(newpw->pw_name, buf, p - buf) == 0) {			fprintf(tempfp,"%s:%s:%d:%d:%s:%s:%s\n",			    oldpw->pw_name,			    newpw->pw_passwd,			    oldpw->pw_uid,			    oldpw->pw_gid,			    oldpw->pw_gecos,			    oldpw->pw_dir,			    oldpw->pw_shell);		}		else			fputs(buf, tempfp);	}	fclose(filefp);	fflush(tempfp);	if(ferror(tempfp)) {		fputs("yppasswdd: ", stderr);		perror("fflush()");		fclose(tempfp);		goto cleanup;	}	fclose(tempfp);	/* Original version of Sun code that fails when  /etc/yp	 * is a symbolic link to  /usr/etc/yp	 */	if (rename(temp, file) < 0) {		fprintf(stderr, "yppasswdd: "); perror("rename");		unlink(temp);		goto cleanup_noclose;	}	/* make sure that original file is secure */	chmod(file, 0644);		ans = 0;	if (mflag && fork() == 0) {		strcpy(cmdbuf, "make");		for (i = 3; i < Argc; i++) {			strcat(cmdbuf, " ");			strcat(cmdbuf, Argv[i]);		}		(void) umask(022);		system(cmdbuf);		exit(0);	}    cleanup:	unlink(temp);	close(tempfd);    cleanup_noclose:	signal(SIGHUP, f1);	signal(SIGINT, f2);	signal(SIGQUIT, f3);    done:	if (!svc_sendreply(transp, xdr_int, &ans))		fprintf(stderr, "yppasswdd: couldnt reply to RPC call\n");}rresvport(){	struct sockaddr_in sin;	int s, alport = IPPORT_RESERVED - 1;	sin.sin_family = AF_INET;	sin.sin_addr.s_addr = 0;#if 0	s = socket(AF_INET, SOCK_DGRAM, 0, 0);#endif	s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);	if (s < 0)		return (-1);	for (;;) {		sin.sin_port = htons((u_short)alport);		if (bind(s, (caddr_t)&sin, sizeof (sin), 0) >= 0)			return (s);		if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) {			perror("socket");			return (-1);		}		(alport)--;		if (alport == IPPORT_RESERVED/2) {			fprintf(stderr, "socket: All ports in use\n");			return (-1);		}	}}static char *pwskip(p)register char *p;{	while( *p && *p != ':' && *p != '\n' )		++p;	if( *p ) *p++ = 0;	return(p);}pwcmp(s1,s2)register char *s1, *s2;{        while (*s1 == *s2)            /* bump while they match */              {              *s1++;              *s2++;              }        if(*s1 == '\0' && *s2 == ':')  /* format specific solution */                         return(0);	return(1);} struct passwd *getpwnam(name)	char *name;{	FILE *pwf;	int cnt;	char *p;	static char line[BUFSIZ+1];	static struct passwd passwd;		pwf = fopen(file, "r");	if (pwf == NULL)		return (NULL);	cnt = strlen(name);	while ((p = fgets(line, BUFSIZ, pwf)) && pwcmp(name, line))		continue;	if (p) {		passwd.pw_name = p;		p = pwskip(p);		passwd.pw_passwd = p;		p = pwskip(p);		passwd.pw_uid = atoi(p);		p = pwskip(p);		passwd.pw_gid = atoi(p);		passwd.pw_quota = 0;		passwd.pw_comment = "";		p = pwskip(p);		passwd.pw_gecos = p;		p = pwskip(p);		passwd.pw_dir = p;		p = pwskip(p);		passwd.pw_shell = p;		while(*p && *p != '\n') p++;		*p = '\0';		fclose(pwf);		return (&passwd);	}	else {		fclose(pwf);		return (NULL);	}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?