1 /* callin.c
2    Check a login name and password against the UUCP password file.
3 
4    Copyright (C) 1992, 1993, 1995, 2002 Ian Lance Taylor
5 
6    This file is part of the Taylor UUCP uuconf library.
7 
8    This library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Library General Public License
10    as published by the Free Software Foundation; either version 2 of
11    the License, or (at your option) any later version.
12 
13    This library is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Library General Public License for more details.
17 
18    You should have received a copy of the GNU Library General Public
19    License along with this library; if not, write to the Free Software
20    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
21 
22    The author of the program may be contacted at ian@airs.com.
23    */
24 
25 #include "uucnfi.h"
26 
27 #if USE_RCS_ID
28 const char _uuconf_callin_rcsid[] = "$FreeBSD$";
29 #endif
30 
31 #include <errno.h>
32 
33 static int ipcheck P((pointer pglobal, int argc, char **argv,
34 		      pointer pvar, pointer pinfo));
35 
36 struct sinfo
37 {
38   int (*pcmpfn) P((int, pointer, const char *));
39   pointer pinfo;
40   boolean ffound;
41   boolean fmatched;
42 };
43 
44 /* Check a login name and password against the UUCP password file.
45    This looks at the Taylor UUCP password file, but will work even if
46    uuconf_taylor_init was not called.  It accepts either spaces or
47    colons as field delimiters.  */
48 
49 int
uuconf_callin(pglobal,pcmpfn,pinfo)50 uuconf_callin (pglobal, pcmpfn, pinfo)
51      pointer pglobal;
52      int (*pcmpfn) P((int, pointer, const char *));
53      pointer pinfo;
54 {
55   struct sglobal *qglobal = (struct sglobal *) pglobal;
56   int iret;
57   char **pz;
58   struct uuconf_cmdtab as[1];
59   struct sinfo s;
60   char *zline;
61   size_t cline;
62 
63   /* If we have no password file names, fill in the default name.  */
64   if (qglobal->qprocess->pzpwdfiles == NULL)
65     {
66       char ab[sizeof NEWCONFIGLIB + sizeof PASSWDFILE - 1];
67 
68       memcpy ((pointer) ab, (pointer) NEWCONFIGLIB,
69 	      sizeof NEWCONFIGLIB - 1);
70       memcpy ((pointer) (ab + sizeof NEWCONFIGLIB - 1), (pointer) PASSWDFILE,
71 	      sizeof PASSWDFILE);
72       iret = _uuconf_iadd_string (qglobal, ab, TRUE, FALSE,
73 				  &qglobal->qprocess->pzpwdfiles,
74 				  qglobal->pblock);
75       if (iret != UUCONF_SUCCESS)
76 	return iret;
77     }
78 
79   as[0].uuconf_zcmd = NULL;
80 
81   s.pcmpfn = pcmpfn;
82   s.pinfo = pinfo;
83   s.ffound = FALSE;
84   s.fmatched = FALSE;
85 
86   zline = NULL;
87   cline = 0;
88 
89   iret = UUCONF_SUCCESS;
90 
91   for (pz = qglobal->qprocess->pzpwdfiles; *pz != NULL; pz++)
92     {
93       FILE *e;
94 
95       e = fopen (*pz, "r");
96       if (e == NULL)
97 	{
98 	  if (FNO_SUCH_FILE ())
99 	    continue;
100 	  qglobal->ierrno = errno;
101 	  iret = UUCONF_FOPEN_FAILED | UUCONF_ERROR_ERRNO;
102 	  break;
103 	}
104 
105       qglobal->ilineno = 0;
106 
107       iret = UUCONF_SUCCESS;
108 
109       while (getline (&zline, &cline, e) > 0)
110 	{
111 	  char *z0, *z1;
112 
113 	  ++qglobal->ilineno;
114 
115 	  /* We have a few hacks to make Unix style passwd files work.
116 	     1) We turn the first two colon characters into spaces.
117 	     2) If the colon characters are adjacent, we assume there
118 	        is no password, and we skip the entry.
119 	     3) If the password between colon characters contains a
120 	        space, we assume that it has been disabled, and we
121 		skip the entry.  */
122 	  z0 = strchr (zline, ':');
123 	  if (z0 != NULL)
124 	    {
125 	      *z0 = ' ';
126 	      z1 = strchr (z0, ':');
127 	      if (z1 != NULL)
128 		{
129 		  if (z1 - z0 == 1)
130 		    continue;
131 		  *z1 = '\0';
132 		  if (strchr (z0 + 1, ' ') != NULL)
133 		    continue;
134 		}
135 	    }
136 	  iret = uuconf_cmd_line (pglobal, zline, as, (pointer) &s,
137 				  ipcheck, 0, (pointer) NULL);
138 	  if ((iret & UUCONF_CMDTABRET_EXIT) != 0)
139 	    {
140 	      iret &=~ UUCONF_CMDTABRET_EXIT;
141 	      if (iret != UUCONF_SUCCESS)
142 		iret |= UUCONF_ERROR_LINENO;
143 	      break;
144 	    }
145 
146 	  iret = UUCONF_SUCCESS;
147 	}
148 
149       (void) fclose (e);
150 
151       if (iret != UUCONF_SUCCESS || s.ffound)
152 	break;
153     }
154 
155   if (zline != NULL)
156     free ((pointer) zline);
157 
158   if (iret != UUCONF_SUCCESS)
159     {
160       qglobal->zfilename = *pz;
161       iret |= UUCONF_ERROR_FILENAME;
162     }
163   else if (! s.ffound || ! s.fmatched)
164     iret = UUCONF_NOT_FOUND;
165 
166   return iret;
167 }
168 
169 /* This is called on each line of the file.  It checks to see if the
170    login name from the file is the one we are looking for.  If it is,
171    it sets ffound, and then sets fmatched according to whether the
172    password matches or not.  */
173 
174 static int
ipcheck(pglobal,argc,argv,pvar,pinfo)175 ipcheck (pglobal, argc, argv, pvar, pinfo)
176      pointer pglobal ATTRIBUTE_UNUSED;
177      int argc;
178      char **argv;
179      pointer pvar ATTRIBUTE_UNUSED;
180      pointer pinfo;
181 {
182   struct sinfo *q = (struct sinfo *) pinfo;
183 
184   if (argc != 2)
185     return UUCONF_SYNTAX_ERROR | UUCONF_CMDTABRET_EXIT;
186 
187   if (! (*q->pcmpfn) (0, q->pinfo, argv[0]))
188     return UUCONF_CMDTABRET_CONTINUE;
189 
190   q->ffound = TRUE;
191   q->fmatched = (*q->pcmpfn) (1, q->pinfo, argv[1]) != 0;
192 
193   return UUCONF_CMDTABRET_EXIT;
194 }
195