Back to index

courier  0.68.2
changepw.c
Go to the documentation of this file.
00001 #include "config.h"
00002 /*
00003 ** Copyright 2000-2006 Double Precision, Inc.  See COPYING for
00004 ** distribution information.
00005 */
00006 
00007 #include      "auth.h"
00008 #include      <courierauth.h>
00009 #include      <stdlib.h>
00010 #include      <stdio.h>
00011 #include      <string.h>
00012 #include      <signal.h>
00013 #include      <unistd.h>
00014 #include      <errno.h>
00015 #include      <sys/time.h>
00016 #include      <sys/select.h>
00017 #include      "htmllibdir.h"
00018 #include      "numlib/numlib.h"
00019 #if HAVE_SYS_WAIT_H
00020 #include      <sys/wait.h>
00021 #endif
00022 #ifndef WEXITSTATUS
00023 #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
00024 #endif
00025 #ifndef WIFEXITED
00026 #define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
00027 #endif
00028 
00029 
00030 
00031 static int badstr(const char *p)
00032 {
00033        while (p && *p)
00034        {
00035               if ((int)(unsigned char)*p < ' ')
00036                      return 1;
00037               ++p;
00038        }
00039        return 0;
00040 }
00041 
00042 int changepw(const char *service,
00043             const char *uid,
00044             const char *opwd,
00045             const char *npwd)
00046 {
00047        pid_t p, p2;
00048        int waitstat;
00049        int pipefd[2];
00050        FILE *fp;
00051 
00052        if (badstr(uid) || badstr(opwd) || badstr(npwd))
00053        {
00054               errno=EINVAL;
00055               return -1;
00056        }
00057 
00058        signal(SIGCHLD, SIG_DFL);
00059        signal(SIGPIPE, SIG_IGN);
00060 
00061         if (pipe(pipefd) < 0)
00062         {
00063                 perror("CRIT: authdaemon: pipe() failed");
00064                 errno=EINVAL;
00065                 return (-1);
00066         }
00067 
00068         p=fork();
00069 
00070         if (p == 0)
00071         {
00072                 char *argv[2];
00073 
00074               argv[0]=SQWEBPASSWD;
00075               argv[1]=0;
00076               dup2(pipefd[0], 0);
00077               close(pipefd[0]);
00078               close(pipefd[1]);
00079               execv(argv[0], argv);
00080                 perror("CRIT: failed to execute " SQWEBPASSWD);
00081               exit(1);
00082        }
00083 
00084        close(pipefd[0]);
00085 
00086        if ((fp=fdopen(pipefd[1], "w")) != 0)
00087        {
00088               fprintf(fp, "%s\t%s\t%s\t%s\n",
00089                      service, uid, opwd, npwd);
00090               fclose(fp);
00091        }
00092        close(pipefd[1]);
00093 
00094         while ((p2=wait(&waitstat)) != p)
00095         {
00096                 if (p2 < 0 && errno == ECHILD)
00097                 {
00098                         perror("CRIT: authdaemon: wait() failed");
00099                         errno=EPERM;
00100                         return (-1);
00101                 }
00102         }
00103 
00104         if (WIFEXITED(waitstat) && WEXITSTATUS(waitstat) == 0)
00105                 return (0);
00106 
00107        errno=EPERM;
00108        return (-1);
00109 }