1 /* pwcheck.c -- Unix pwcheck daemon
2 $Id: pwcheck.c,v 1.8 2001/12/04 02:06:51 rjs3 Exp $
3 Copyright 1998, 1999 Carnegie Mellon University
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the name of Carnegie Mellon
12 University not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior
16 CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
17 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
18 FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR
19 ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
21 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
22 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/socket.h>
43 #if !defined(_PATH_PWCHECKPID)
45 # define _PATH_PWCHECKPID (_PATH_VARRUN "pwcheck.pid")
47 # define _PATH_PWCHECKPID (NULL)
52 int retry_write(int, const char *, unsigned int);
55 * Unix pwcheck daemon-authenticated login (shadow password)
61 char fnamebuf[MAXPATHLEN];
66 struct sockaddr_un srvaddr;
67 struct sockaddr_un clientaddr;
71 char *pid_file = _PATH_PWCHECKPID;
75 openlog("pwcheck", LOG_NDELAY, LOG_AUTH);
83 _exit(0); /* parent dies */
85 if ((pid == -1) && (errno == EAGAIN)) {
86 syslog(LOG_WARNING, "master fork failed (sleeping): %m");
93 syslog(LOG_ERR, "FATAL: master fork failed: %m");
94 fprintf(stderr, "pwcheck: ");
101 * We're now running in the child. Lose our controlling terminal
102 * and obtain a new process group.
104 if (setsid() == -1) {
106 syslog(LOG_ERR, "FATAL: setsid: %m");
107 fprintf(stderr, "pwcheck: ");
113 s = open("/dev/null", O_RDWR, 0);
116 syslog(LOG_ERR, "FATAL: /dev/null: %m");
117 fprintf(stderr, "pwcheck: ");
123 dup2(s, fileno(stdin));
124 dup2(s, fileno(stdout));
125 dup2(s, fileno(stderr));
131 * Record process ID - shamelessly stolen from inetd (I.V.)
135 fp = fopen(pid_file, "w");
138 fprintf(fp, "%ld\n", (long)pid);
140 } else if (pid_file) {
141 syslog(LOG_WARNING, "%s: %m", pid_file);
144 s = socket(AF_UNIX, SOCK_STREAM, 0);
150 strncpy(fnamebuf, PWCHECKDIR, sizeof(fnamebuf));
151 strncpy(fnamebuf + sizeof(PWCHECKDIR)-1, "/pwcheck",
152 sizeof(fnamebuf) - sizeof(PWCHECKDIR));
153 fnamebuf[MAXPATHLEN-1] = '\0';
155 (void) unlink(fnamebuf);
157 memset((char *)&srvaddr, 0, sizeof(srvaddr));
158 srvaddr.sun_family = AF_UNIX;
159 strncpy(srvaddr.sun_path, fnamebuf, sizeof(srvaddr.sun_path));
160 /* Most systems make sockets 0777 no matter what you ask for.
161 Known exceptions are Linux and DUX. */
162 oldumask = umask((mode_t) 0); /* for Linux, which observes the umask when
163 setting up the socket */
164 r = bind(s, (struct sockaddr *)&srvaddr, sizeof(srvaddr));
166 syslog(LOG_ERR, "%.*s: %m",
167 sizeof(srvaddr.sun_path), srvaddr.sun_path);
170 umask(oldumask); /* for Linux */
171 chmod(fnamebuf, (mode_t) 0777); /* for DUX, where this isn't the default.
172 (harmlessly fails on some systems) */
175 syslog(LOG_ERR, "listen: %m");
180 len = sizeof(clientaddr);
181 c = accept(s, (struct sockaddr *)&clientaddr, &len);
182 if (c == -1 && errno != EINTR) {
183 syslog(LOG_WARNING, "accept: %m");
191 void newclient(int c)
197 extern char *pwcheck();
200 while (start < sizeof(request) - 1) {
201 n = read(c, request+start, sizeof(request) - 1 - start);
203 reply = "Error reading request";
209 if (request[start-1] == '\0' && strlen(request) < start) {
214 if (start >= sizeof(request) - 1) {
215 reply = "Request too big";
218 reply = pwcheck(request, request + strlen(request) + 1);
223 retry_write(c, reply, strlen(reply));
228 * Keep calling the write() system call with 'fd', 'buf', and 'nbyte'
229 * until all the data is written out or an error occurs.
231 int retry_write(int fd, const char *buf, unsigned int nbyte)
240 n = write(fd, buf, nbyte);
249 if ((unsigned int) n >= nbyte)