mountd.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 2,539 行 · 第 1/5 页

C
2,539
字号
#endif			/*			 * Make saved /etc/exports time older to force			 * a re-build of the in core structure.			 */			exportstat.st_mtime--;			set_exports();			mtd_export(transp);			return;		default:			svcerr_noproc(transp);			return;	}}struct hostent *getclientsname(rqstp,transp)	struct svc_req *rqstp;	SVCXPRT *transp;{	struct in_addr claim;	struct sockaddr_in actual;	struct hostent *hp, *chp;	static struct hostent h;	static struct in_addr prev;	static char *null_alias;	char *machine;	char *cp;	char *strchr ();	int i;			if (rqstp->rq_cred.oa_flavor != AUTH_UNIX) {		return(NULL);	}	actual = *svc_getcaller(transp);	if (nfs_portmon) {		if (ntohs(actual.sin_port) >= IPPORT_RESERVED) {			return(NULL);		}	}        /*         * Don't use the unix credentials to get the machine name,         * instead use the source IP address.  Use cached hostent         * if previous request was from same client.         */        if (bcmp(&actual.sin_addr, &prev, sizeof(struct in_addr)) == 0) {#ifdef DEBUG                (void)fprintf(stderr, "Found addr in hostent cache! \n");#endif DEBUG                return (&h);	}        hp = gethostbyaddr((char *) &actual.sin_addr, sizeof(actual.sin_addr),                           AF_INET);        if (hp == NULL) {		if (ipaddr_check) {                	svcerr_auth(transp, AUTH_BADCRED);                	return(NULL);		} /* else dummy one up */		h.h_name = (char *)inet_ntoa(actual.sin_addr);#ifdef DEBUG                (void)fprintf(stderr, "Dummy hostent name %s\n", h.h_name);#endif DEBUG                h.h_aliases = &null_alias;                h.h_addrtype = AF_INET;                h.h_length = sizeof (u_long);                hp = &h;        } else {        	bcopy(hp, &h, sizeof(struct hostent));	}        prev = actual.sin_addr;#ifdef DEBUG	(void)fprintf(stderr, "getclientsname %s\n", hp->h_name);#endif DEBUG	/*	 *	If domain_check or subdomain_check is set and	 *	if BIND enabled, check the requester's domain spec	 *	to be sure it is local.  Check if:	 *		1) domain spec matches that of local host or	 *		2) host name is unqualified (local)	 */	if ((domain_check || subdomain_check) && (bindup()) != NULL) {                machine = ((struct authunix_parms *)                        rqstp->rq_clntcred)->aup_machname;                chp = gethostbyname(machine);                if (chp == NULL) {                        svcerr_auth(transp,AUTH_BADCRED);                        return(NULL);                }		for (i=0; i<MAXADDRS; i++) {			if (chp->h_addr_list[i] == NULL)				return(NULL);                	bcopy(chp->h_addr_list[i], &claim, sizeof(struct in_addr));                	if (actual.sin_addr.s_addr == claim.s_addr)				break;  /* not an imposter */			if (i == (MAXADDRS - 1))				return(NULL);                }		if ((cp = strchr (hp->h_name, '.')) != NULL) {			/* qualified name */			if (strcasecmp (cp+1, _res.defdname) != NULL) {				/*				 * Not in local domain, check  				 * if in subdomain				 */				if (subdomain_check) {#ifdef DEBUG					(void) fprintf (stderr, "mountd: client, %s not local domain member, check if %s is a subdomain of %s\n", hp->h_name, cp+1, _res.defdname);#endif DEBUG					if ((strfind (cp+1, _res.defdname)) == NULL) {						syslog(LOG_ERR, "warning: (u)mount attempt from client %s, not a local subdomain member", hp->h_name);						return (NULL);					}				}				else {					syslog(LOG_ERR, "warning: (u)mount attempt from client %s, not a local domain member", hp->h_name);					return(NULL);				}			}		}	}#ifdef DEBUG	(void) fprintf(stderr, "%s: end ipaddr_check successful\n", pgmname);#endif DEBUG	return(hp);}/* * Check mount requests, add to mounted list if ok */mtd_mount(rqstp, transp)	struct svc_req *rqstp;	SVCXPRT *transp;{	fhandle_t fh;	struct fhstatus fhs;	char *path;	int fd, anc_fd;	struct mountdlist *ml;	struct stat statbuf;	struct exports *ex, *ex2, *ancestors[MAX_LEVELS];	struct exports *saveex = NULL;	int found=0, success=0, bestposs=1, index, i;	int first = 1;	struct dupreq *dr;	char *anc_name;	char rpath[MAXPATHLEN];	struct hostent *client;	struct sockaddr_in addr;        if ((client = getclientsname(rqstp,transp))== NULL) {                svcerr_weakauth(transp);                return;        }	path = NULL;	if (!svc_getargs(transp, xdr_path, &path)) {		svcerr_decode(transp);		mtd_abort();		return;	}#ifdef DEBUG	(void) fprintf(stderr, "path is %s\n", path);#endif	if ((fd = open(path, O_RDONLY, 0)) < 0) {		fhs.fhs_status = errno;		perror("mountd: open");		goto done;	}	if (fstat(fd, &statbuf) < 0) {		fhs.fhs_status = errno;		perror("mountd: stat");		(void) close(fd);		goto done;	}        /*         * Now, before we spend a lot of time looking through the         * exports list, lets check to see if we have already handed out         * a filehandle to this requestor. . .         */	addr = *svc_getcaller(transp);        if (dr = dupcache_check(addr.sin_addr, statbuf.st_dev, statbuf.st_ino,                        statbuf.st_gennum)) {		if ((anc_fd = open(dr->rc_ancname, O_RDONLY, 0)) < 0) {			fhs.fhs_status = errno;			perror("mountd: open");			goto done;		}		if (nfs_getfh(fd, anc_fd, &fh) < 0) {			fhs.fhs_status = errno;			syslog(LOG_ERR, "nfs_getfh: %m");			goto done;		}		fhs.fhs_status = 0;                fhs.fhs_fh = fh;		(void)close(anc_fd);                goto done;        }	/*	 * Expand path into its canonical form, resolving symbolic link	 * and ../ components. 	 */	if (realpath(path, rpath) == NULL) {#ifdef DEBUG		perror("mountd");		(void)fprintf(stderr, "Realpath failed on %s\n", path);#endif DEBUG		fhs.fhs_status = EACCES;		goto done;	}	/*	 * Search exports list for a directory with an entry with the	 * same dev_t number.  Search down that dev's list looking for 	 * an exact match.  If none found, look for entries that are	 * an ancestor of the requested path.  Check the access on the	 * closest match.  If access is not allowed, check the next	 * closest, ... until either no more exported ancestors exist	 * or an ancestor is found with allowable access for the client.	 * The export options used will be those on the ancestor found.	 */loop_search:	for (ex = exports; ex != NULL; ex = ex->ex_devptr) {#ifdef DEBUG		(void) fprintf(stderr, "checking %o for %o\n", ex->ex_dev, statbuf.st_dev);#endif		if (ex->ex_dev == statbuf.st_dev) {			for (ex2=ex; ex2 != NULL; ex2 = ex2->ex_next) {#ifdef DEBUG				(void) fprintf(stderr, "checking %s with %s for exact match dir\n", ex2->ex_name, rpath);#endif				if (strcmp(ex2->ex_name, rpath) == NULL) {#ifdef DEBUG					(void) fprintf(stderr, "got exact match dir\n");#endif					if (ex2->ex_groups == NULL) {						success = 1;						break;					}					else {						if ((check_groups(ex2->ex_groups, client->h_name))!=NULL) {							success = 1;							break;						}						else {							/*							 * Exact match found but requester							 * is not an allowable host.  Break							 * to search for an ancestor match.							 */							saveex = ex;							break;						}					}				}			}			if (success) {				if ((anc_fd = open(ex2->ex_name, O_RDONLY, 0)) < 0) {					fhs.fhs_status = errno;					perror("mountd: open");					goto done;				}				anc_name = ex2->ex_name;				goto hit;			}			if (saveex != NULL)				break;			if (ex2 == NULL) {				/*				 * Exact matches failed.  				 * Break to best match search.				 */#ifdef DEBUG				(void) fprintf(stderr,"exact match for %s failed\n", rpath);#endif				saveex = ex;				break;			}		}	}	if (!saveex) {		if (first) {			first = 0;			exportstat.st_mtime--;			set_exports();			goto loop_search;		}		else {#ifdef DEBUG			(void) fprintf(stderr, "%s: filesystem %s not found\n", pgmname, rpath);#endif DEBUG			fhs.fhs_status = EACCES;			goto done;		}	}	/*	 * Using pointer to directory exports record with same	 * dev_t number, try to find best match.	 */	ex = saveex;	if (ex->ex_dev == statbuf.st_dev) {		/*		 *  initialize ancestors		 */		for (i=0; i< MAX_LEVELS; i++)			ancestors[i] = NULL;		for (ex2 = ex; ex2 != NULL; ex2 = ex2->ex_next) {			if ((strcmp(ex2->ex_name, rpath) != NULL) && (index = path_check(ex2->ex_name, rpath)) > bestposs) {#ifdef DEBUG				(void) fprintf(stderr, "ancestor: %s found, level:%d is > bestposs\n", ex2->ex_name, index);#endif				found = 1;				ancestors[index-2] = ex2;			}			else if (index == bestposs) {#ifdef DEBUG				(void) fprintf(stderr, "best match %s found, checking access\n", ex2->ex_name);#endif				if (ex2->ex_groups == NULL) {					success = 1;					break;				}				else {					if ((check_groups(ex2->ex_groups, client->h_name)) != NULL) {						success = 1;						break;					}					else						++bestposs;				}			}		}		if (success) {			if ((anc_fd = open(ex2->ex_name, O_RDONLY, 0)) < 0) {				fhs.fhs_status = errno;				perror("mountd: open");				goto done;			}			anc_name = ex2->ex_name;			goto hit;		}		if (found) {			for (i= ((bestposs==1)? 0:bestposs-2); i< MAX_LEVELS-1; i++)				if (ancestors[i] != NULL) {#ifdef DEBUG					(void) fprintf(stderr, "Checking ancestor: %s for allowable access\n", ancestors[i]->ex_name); #endif DEBUG					if (ancestors[i]->ex_groups == NULL) {						success = 1;						break;					}					else {						if ((check_groups(ancestors[i]->ex_groups, client->h_name)) != NULL) {							success = 1;							break;						}					}				}			if (success) {				if ((anc_fd = open(ancestors[i]->ex_name, O_RDONLY, 0)) < 0) {					fhs.fhs_status = errno;					perror("mountd: open");					goto done;				}				anc_name = ancestors[i]->ex_name;				goto hit;			}		}	}	fhs.fhs_status = EACCES;	goto done;  hit:	if (nfs_getfh(fd, anc_fd, &fh) < 0) {		fhs.fhs_status = errno;		syslog(LOG_ERR, "nfs_getfh: %m");		(void)close(anc_fd);		goto done;	}	fhs.fhs_status = 0;	fhs.fhs_fh = fh;	(void)close(anc_fd);        /*         * Now that we have a "New" mount request, lets tuck it into the         * dupreq cache so that if the client retransmits, we can reply	 * with the filehandle immediately.         */        dupcache_enter(addr.sin_addr, statbuf.st_dev, statbuf.st_ino,                    statbuf.st_gennum, anc_name);done:#ifdef DEBUG        (void) fprintf(stderr, "*** ng cache and export list ***\n");        print_ngcache();        print_exports(exports);#endif DEBUG	(void) close(fd);	if (!svc_sendreply(transp, xdr_fhstatus, &fhs)) {		syslog(LOG_ERR, "couldn't reply to MOUNT rpc call");		mtd_abort();	} 	else  {		for (ml = mountlist; ml != NULL; ml = ml->ml_nxt) {			if (strcmp(ml->ml_path, rpath) == 0 &&		    	    strcmp(ml->ml_name, client->h_name) == 0)				break;		}		if (ml == NULL) {			ml = (struct mountdlist *)exmalloc(sizeof(struct mountdlist));			ml->ml_path = (char *)exmalloc(strlen(rpath) + 1);			(void) strcpy(ml->ml_path, rpath);			ml->ml_name = (char *)exmalloc(strlen(client->h_name) + 1);			(void) strcpy(ml->ml_name, client->h_name);			ml->ml_nxt = mountlist;			mountlist = ml;			ml->ml_pos = rmtab_insert(client->h_name, rpath);		}	}	svc_freeargs(transp, xdr_path, &path);}/* * Check if machine is in groups structure.  If not, call YP. */check_groups(headgl, mach)	struct groups *headgl;	char *mach;{	struct groups *gl;	int length;	/* 	 * first check for exact match on machine name	 */	for (gl = headgl; gl != NULL; gl = gl->g_next){ #ifdef DEBUG		(void) fprintf(stderr, "checking machines: %s for %s\n", gl->g_name, mach);#endif		if (strcasecmp(gl->g_name, mach) == 0) {			gl->g_hbit = 1;			return(TRUE);		}		else if (((length = local_hostname_length(mach)) != NULL) && 			  (strlen(gl->g_name) == length) &&			  (strncasecmp(gl->g_name, mach, length) == 0)) {			gl->g_hbit = 1;			return(TRUE);		}	}	/*	 * now check netgroups	 */	for (gl = headgl; gl != NULL; gl = gl->g_next){ #ifdef DEBUG		(void) fprintf(stderr, "checking innetgr: %s for %s\n", gl->g_name, mach);#endif		if (gl->g_hbit)			continue;		if (innetgr_cache (gl->g_name, mach, &gl->g_hbit)) {			return(TRUE);		}	}	return(FALSE);}/* * Check the pathnames of the export name and the desired mount * pathname. */path_check(list_name, name) 	char *list_name, *name;{ 	char *ch1, *ch2; 	char *ch11, *ch22; 	char s1, s2; 	int done, level=0; 	char *index();  #ifdef DEBUG	(void) fprintf(stderr, "path_check %s with %s\n", list_name, name);#endif 	if (!strcmp(list_name, "/")) 		return(TRUE); 	ch1 = list_name; 	ch2 = name; 	done = 0; 	while (!done) { 		if ((ch1 = goto_char(ch1)) != NULL) 			ch11 = index(ch1, '/'); 		if ((ch2 = goto_char(ch2)) != NULL) 			ch22 = index(ch2, '/'); 		if (ch11 && *ch11 != '\0') { 			s1 = *ch11; 			*ch11 = '\0'; 			ch11++; 		} 		if (ch22 && *ch22 != '\0') { 			s2 = *ch22; 			*ch22 = '\0'; 			ch22++; 		}

⌨️ 快捷键说明

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