openafs: Improved calling of get-token script
[hcoop/debian/courier-authlib.git] / authsyschangepwd.c
CommitLineData
d9898ee8 1/*
2** Copyright 2001-2006 Double Precision, Inc. See COPYING for
3** distribution information.
4*/
5
6#if HAVE_CONFIG_H
7#include "courier_auth_config.h"
8#endif
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12#include <signal.h>
13#include <errno.h>
14#if HAVE_UNISTD_H
15#include <unistd.h>
16#endif
17#include <pwd.h>
18#include <sys/types.h>
19#include <fcntl.h>
20#include "auth.h"
21#include "authwait.h"
22#include "authchangepwdir.h"
23#include "numlib/numlib.h"
24
d9898ee8 25
26static int dochangepwd(struct passwd *, const char *, const char *);
27
28int auth_syspasswd(const char *service, /* Ignored */
29 const char *userid, /* Generally ignored */
30 const char *oldpwd, /* Old password */
31 const char *newpwd) /* New password */
32{
33 char *cpy=strdup(userid);
34 struct passwd *pwd;
35 int rc;
36
37 if (!cpy)
38 {
39 perror("malloc");
40 errno=EPERM;
41 return (-1);
42 }
43
44 if (strchr(cpy, '@'))
45 {
46 free(cpy);
47 errno=EINVAL;
48 return (-1);
49 }
50
51 pwd=getpwnam(cpy);
52
53 if (!pwd)
54 {
55 free(cpy);
56 errno=EINVAL;
57 return (-1);
58 }
59
60 rc=dochangepwd(pwd, oldpwd, newpwd);
61
62 free(cpy);
63 if (rc == 0)
64 return rc;
65
66 return (1); /* Fatal error */
67}
68
69#define EXPECT AUTHCHANGEPWDIR "/authsystem.passwd"
70
71static int dochangepwd(struct passwd *pwd,
72 const char *oldpwd, const char *newpwd)
73{
74 pid_t p, p2;
75 int pipefd[2];
76 int waitstat;
77 FILE *fp;
78
79 signal(SIGCHLD, SIG_DFL);
80 signal(SIGTERM, SIG_DFL);
81
82 if (pipe(pipefd) < 0)
83 {
84 perror("CRIT: authsyschangepwd: pipe() failed");
85 errno=EPERM;
86 return (-1);
87 }
88
89 p=fork();
90
91 if (p < 0)
92 {
93 close(pipefd[0]);
94 close(pipefd[1]);
95 perror("CRIT: authsyschangepwd: fork() failed");
96 errno=EPERM;
97 return (-1);
98 }
99
100 if (p == 0)
101 {
102 char *argv[2];
103
104 dup2(pipefd[0], 0);
105 close(pipefd[0]);
106 close(pipefd[1]);
107
108 close(1);
109 open("/dev/null", O_WRONLY);
110 dup2(1, 2);
111
112 if (pwd->pw_uid != getuid())
113 {
114#if HAVE_SETLOGIN
115#if HAVE_SETSID
116 if (setsid() < 0)
117 {
118 perror("setsid");
119 exit(1);
120 }
121#endif
122
123 setlogin(pwd->pw_name);
124#endif
125 libmail_changeuidgid(pwd->pw_uid, pwd->pw_gid);
126 }
127
128 argv[0]=EXPECT;
129 argv[1]=0;
130
131 execv(argv[0], argv);
132 perror("exec");
133 exit(1);
134 }
135
136 close(pipefd[0]);
137 signal(SIGPIPE, SIG_IGN);
138
139 if ((fp=fdopen(pipefd[1], "w")) == NULL)
140 {
141 perror("CRIT: authsyschangepwd: fdopen() failed");
142 kill(p, SIGTERM);
143 }
144 else
145 {
146 fprintf(fp, "%s\n%s\n", oldpwd, newpwd);
147 fclose(fp);
148 }
149 close(pipefd[1]);
150
151 while ((p2=wait(&waitstat)) != p)
152 {
153 if (p2 < 0 && errno == ECHILD)
154 {
155 perror("CRIT: authsyschangepwd: wait() failed");
156 errno=EPERM;
157 return (-1);
158 }
159 }
160
161 if (WIFEXITED(waitstat) && WEXITSTATUS(waitstat) == 0)
162 return (0);
163 errno=EPERM;
164 return (-1);
165}