imapext-2007

annotate APOPtools/apopcall.c @ 4:d741b3ecc917

imapext-2007f
author HIROSE Yuuji <yuuji@gentei.org>
date Thu, 30 Oct 2014 00:03:05 +0900
parents 28a55bc1110c
children
rev   line source
yuuji@1 1 #include <stdio.h>
yuuji@1 2 #include <stdlib.h>
yuuji@1 3 #include <string.h>
yuuji@1 4 #include <unistd.h>
yuuji@1 5 #include <sys/types.h>
yuuji@1 6 #include <sys/wait.h>
yuuji@1 7 #include <sys/stat.h>
yuuji@1 8 #include <pwd.h>
yuuji@1 9 #ifdef SHADOW_PASSWD
yuuji@1 10 #include <shadow.h>
yuuji@1 11 #endif
yuuji@1 12
yuuji@1 13 #ifndef APOPPASSWD
yuuji@1 14 #define APOPPASSWD "/usr/local/bin/apoppasswd"
yuuji@1 15 #endif
yuuji@1 16 #ifndef APOPFILEBASE
yuuji@1 17 #define APOPFILEBASE ".apop"
yuuji@1 18 #endif
yuuji@1 19 #ifndef XADDR_DELIM
yuuji@1 20 #define XADDR_DELIM ('-')
yuuji@1 21 #endif
yuuji@1 22
yuuji@1 23 char *myname;
yuuji@1 24
yuuji@1 25 int ishexa(int c) {
yuuji@1 26 strchr("0123456789ABCDFabcdef", c) ? 1 : 0;
yuuji@1 27 }
yuuji@1 28
yuuji@1 29 put_form(email, pass, new, new2, suffix, hidden, auth, force)
yuuji@1 30 char *email, *pass, *new, *new2, *suffix;
yuuji@1 31 int hidden, auth, force;
yuuji@1 32 /* auth = 0: old password
yuuji@1 33 1: base addresse's mail password
yuuji@1 34 2: unix password */
yuuji@1 35 {
yuuji@1 36 char *authtype[] = {"old", "base", "unix"};
yuuji@1 37 char *var[] = {"email", "pass", "new", "new2", "auth", ""};
yuuji@1 38 char *val[] = {email, pass, new, new2, authtype[auth]};
yuuji@1 39 char *prm[] = {"", /* "ユーザ名", */
yuuji@1 40 auth ?
yuuji@1 41 ((auth==1)
yuuji@1 42 ? "基本メイルアドレス用パスワード<br>Password for Basic Mail address"
yuuji@1 43 : "UNIXログインパスワード<br>UNIX login Password")
yuuji@1 44 : "古いメイルパスワード<br>Old Mail Password",
yuuji@1 45 "新しいメイルパスワード<br>New Mail Password",
yuuji@1 46 "新パスワードをもう一回(確認)<br>New Mail Password Again",
yuuji@1 47 ""};
yuuji@1 48 int h=0, i;
yuuji@1 49
yuuji@1 50 printf("<form method=POST action\"./%s\">\n", myname);
yuuji@1 51 printf(" <table border=1>\n");
yuuji@1 52 for (i=0; var[i][0]; i++) {
yuuji@1 53 h = hidden || strstr("email,suffix,auth", var[i]);
yuuji@1 54 if (prm[i][0]) {
yuuji@1 55 printf("<tr><td>%s</td><td>", prm[i]);
yuuji@1 56 } else {
yuuji@1 57 }
yuuji@1 58 printf("<input name=%s %svalue=\"%s\" length=40 maxlength=40>\n",
yuuji@1 59 var[i],
yuuji@1 60 h ? "type=hidden "
yuuji@1 61 : (strstr(prm[i], "パスワード") ? "type=password " : "<br>"),
yuuji@1 62 val[i]);
yuuji@1 63 if (!strcmp(var[i], "suffix")) {
yuuji@1 64 /* ここでは suffix を入れさせない方がいいかも */
yuuji@1 65 /* 表向きのメイルアドレスを表示しておく */
yuuji@1 66 printf("%s", email);
yuuji@1 67 /* if (suffix[0]) {
yuuji@1 68 printf("-%s", suffix);
yuuji@1 69 } */
yuuji@1 70 if (auth)
yuuji@1 71 printf("<br>(新規作成:New Account)");
yuuji@1 72 }
yuuji@1 73 if (prm[i][0])
yuuji@1 74 printf("</td></tr>");
yuuji@1 75 printf("\n");
yuuji@1 76 }
yuuji@1 77
yuuji@1 78 printf("</table>\n");
yuuji@1 79 if (force)
yuuji@1 80 printf("<input name=force type=hidden value=ON>\n");
yuuji@1 81 if (auth) {
yuuji@1 82 char *a[] = {"basic", "unix"};
yuuji@1 83 printf("<input type=hidden name=auth value=\"%s\">\n", a[auth-1]);
yuuji@1 84 }
yuuji@1 85 printf("<input name=OK value=OK type=submit>\n");
yuuji@1 86 printf("<input name=RESET value=RESET type=reset>\n");
yuuji@1 87 printf("</form>\n");
yuuji@1 88 fflush(stdout);
yuuji@1 89 }
yuuji@1 90
yuuji@1 91 char *decode(char *code) {
yuuji@1 92 int l=1+strlen(code);
yuuji@1 93 int i, c, d;
yuuji@1 94 char *ret = (char*)malloc(l*sizeof(char));
yuuji@1 95 char *p = code;
yuuji@1 96 memset(ret, 0, l);
yuuji@1 97 for (i=0; i<strlen(code); i++) {
yuuji@1 98 if (code[i] == '+') code[i] = ' ';
yuuji@1 99 }
yuuji@1 100 while (code[0] && (p=strchr(code, '%'))
yuuji@1 101 && ishexa(*(p+1)) && ishexa(*(p+2))) {
yuuji@1 102 *(p++) = '\0';
yuuji@1 103 strncat(ret, code, l);
yuuji@1 104 c = (islower(*p) ? toupper(*p) : *p) - '0';
yuuji@1 105 p++;
yuuji@1 106 d = (islower(*p) ? toupper(*p) : *p) - '0';
yuuji@1 107 if (c > 9) c -= ('A'-'9'-1);
yuuji@1 108 if (d > 9) d -= ('A'-'9'-1);
yuuji@1 109 ret[strlen(ret)] = c*16+d;
yuuji@1 110 code = p+1;
yuuji@1 111 }
yuuji@1 112 if (code[0]) strncat(ret, code, l);
yuuji@1 113 return ret;
yuuji@1 114 }
yuuji@1 115
yuuji@1 116 #define BSIZE 8192
yuuji@1 117 char **decode_post() {
yuuji@1 118 char *buf = (char*)malloc(BSIZE*sizeof(char));
yuuji@1 119 char **post, *p = buf;
yuuji@1 120 int n=0, i;
yuuji@1 121 post = (char**)calloc(1, sizeof(char*));
yuuji@1 122 *buf = '\0';
yuuji@1 123 fgets(buf, BSIZE, stdin);
yuuji@1 124 if (strchr("\n\r", buf[strlen(buf)-1])) /* chop */
yuuji@1 125 buf[strlen(buf)-1] = '\0';
yuuji@1 126 while (buf[0] && NULL != (p=strchr(buf, '&'))) {
yuuji@1 127 *p = '\0';
yuuji@1 128 post[n] = (char*)malloc((p-buf+1)*sizeof(char));
yuuji@1 129 strcpy(post[n], buf);
yuuji@1 130 n++;
yuuji@1 131 post = (char**)realloc(post, (1+n)*sizeof(char*));
yuuji@1 132 buf = 1+p;
yuuji@1 133 }
yuuji@1 134 if (buf[0]) post[n++] = buf;
yuuji@1 135 /* decode URL encoded */
yuuji@1 136 for (i=0; i < n; i++) {
yuuji@1 137 char *p;
yuuji@1 138 p=post[i];
yuuji@1 139 post[i] = decode(p);
yuuji@1 140 }
yuuji@1 141 post[i] = ""; /* terminator */
yuuji@1 142 return post;
yuuji@1 143 }
yuuji@1 144
yuuji@1 145 void footer() {
yuuji@1 146 puts("</body>\n</html>");
yuuji@1 147 fflush(stdout);
yuuji@1 148 }
yuuji@1 149
yuuji@1 150 void fail() {
yuuji@1 151 printf("パスワード更新に失敗しました<br>\n");
yuuji@1 152 printf("<a href=\"./\">やり直し</a><br>\n");
yuuji@1 153 footer();
yuuji@1 154 exit(1);
yuuji@1 155 }
yuuji@1 156 void success(char *email) {
yuuji@1 157 printf("<hr>メイルアカウント %s 用のパスワード更新は完了しました。<br>\n",
yuuji@1 158 email);
yuuji@1 159 footer();
yuuji@1 160 exit(0);
yuuji@1 161 }
yuuji@1 162
yuuji@1 163 int apopfile_existp(char *home, char *suffix, uid_t uid) {
yuuji@1 164 struct stat st;
yuuji@1 165 int s;
yuuji@1 166 int len = strlen(home) + 1
yuuji@1 167 + strlen(APOPFILEBASE) + strlen(suffix) + 3;
yuuji@1 168 char *apopfile = (char*)malloc(len);
yuuji@1 169 if (suffix[0]) {
yuuji@1 170 snprintf(apopfile, len, "%s/%s%c%s%c",
yuuji@1 171 home, APOPFILEBASE, XADDR_DELIM, suffix, 0);
yuuji@1 172 } else {
yuuji@1 173 snprintf(apopfile, len, "%s/%s%c", home, APOPFILEBASE, 0);
yuuji@1 174 }
yuuji@1 175 seteuid(uid);
yuuji@1 176 s = stat(apopfile, &st);
yuuji@1 177 seteuid(0);
yuuji@1 178 memset(apopfile, '\0', strlen(apopfile));
yuuji@1 179 free(apopfile);
yuuji@1 180 return !s;
yuuji@1 181 }
yuuji@1 182
yuuji@1 183 #ifndef QMAILCONTROL
yuuji@1 184 # define QMAILCONTROL "/var/qmail/control"
yuuji@1 185 #endif
yuuji@1 186 #ifndef MAILTMPLEN
yuuji@1 187 # define MAILTMPLEN 1024
yuuji@1 188 #endif
yuuji@1 189
yuuji@1 190 /* Convert virtual domain user
yuuji@1 191 */
yuuji@1 192 char* conv_virtualdomain(char *account) {
yuuji@1 193 char *dom = strchr(account, '@'), *p;
yuuji@1 194 char vd[MAILTMPLEN+1], rewrite[MAILTMPLEN+1], previous[MAILTMPLEN+1];
yuuji@1 195 FILE *vdfd;
yuuji@1 196 int match=0;
yuuji@1 197 char buf[MAILTMPLEN+1], *s;
yuuji@1 198 snprintf(vd, MAILTMPLEN, "%s/%s", QMAILCONTROL, "virtualdomains");
yuuji@1 199 if (NULL == dom) return account;
yuuji@1 200 dom++; /* set position of domain part beginning */
yuuji@1 201 if (dom && NULL != (vdfd = fopen (vd, "r"))) {
yuuji@1 202 int l = strlen(dom);
yuuji@1 203 int L = strlen(account);
yuuji@1 204 while ((s=fgets(buf, MAILTMPLEN, vdfd))) {
yuuji@1 205 if (p=strchr(s, '#'))
yuuji@1 206 *p = '\0'; /* zap comments */
yuuji@1 207 if (!strchr(buf, ':'))
yuuji@1 208 continue;
yuuji@1 209 while (s && (strrchr(s, '\n') || strrchr(s, '\r') || strrchr(s, ' ')))
yuuji@1 210 s[strlen(s)-1] = '\0';
yuuji@1 211 if (!strncmp(account, s, L) && s[L] == ':' && s[L+1]) { /* user matches */
yuuji@1 212 match = 3;
yuuji@1 213 snprintf(rewrite, MAILTMPLEN, "%s-%s", s+L+1, account);
yuuji@1 214 break;
yuuji@1 215 }
yuuji@1 216 if (!strncmp(dom, s, l) && s[l] == ':' && s[l+1]) { /* domain matches */
yuuji@1 217 match = 2;
yuuji@1 218 snprintf(rewrite, MAILTMPLEN, "%s%c%s", s+l+1, XADDR_DELIM, account);
yuuji@1 219 continue;
yuuji@1 220 }
yuuji@1 221 if (match < 2 && s[0] == '.') { /* if domain described in wildcard */
yuuji@1 222 if (p=strchr(s, ':')) {
yuuji@1 223 *p = '\0';
yuuji@1 224 if (!strcmp(dom+(strlen(dom)-strlen(s)), s)) {
yuuji@1 225 if (match == 0
yuuji@1 226 || strlen(previous) < strlen(s)) {
yuuji@1 227 match = 1;
yuuji@1 228 strncpy(previous, s, MAILTMPLEN);
yuuji@1 229 snprintf(rewrite, MAILTMPLEN, "%s%c%s", p+1, XADDR_DELIM, account);
yuuji@1 230 }
yuuji@1 231 }
yuuji@1 232 }
yuuji@1 233 }
yuuji@1 234 }
yuuji@1 235 fclose(vdfd);
yuuji@1 236 if (match) {
yuuji@1 237 p = strchr(rewrite, '@');
yuuji@1 238 /* fprintf(stderr, "m=%d, rwr=[%s]\n", match, rewrite); */
yuuji@1 239 if (p) {
yuuji@1 240 *p = '\0';
yuuji@1 241 }
yuuji@1 242 /* fprintf(stderr, "rwr=[%s]\n", rewrite); */
yuuji@1 243 s = malloc(strlen(rewrite)+1);
yuuji@1 244 strncpy(s, rewrite, strlen(rewrite)+1);
yuuji@1 245 memset(vd, 0, sizeof(vd));
yuuji@1 246 memset(rewrite, 0, sizeof(rewrite));
yuuji@1 247 memset(previous, 0, sizeof(previous));
yuuji@1 248 return s;
yuuji@1 249 }
yuuji@1 250 }
yuuji@1 251 /* Then, compare with locals */
yuuji@1 252 snprintf(vd, MAILTMPLEN, "%s/%s", QMAILCONTROL, "locals");
yuuji@1 253 if (NULL != (vdfd=fopen(vd, "r"))) {
yuuji@1 254 while (s=fgets(buf, MAILTMPLEN, vdfd)) {
yuuji@1 255 if (p=strchr(s, '#')) *p = '\0'; /* zap after comment mark # */
yuuji@1 256 while (*s && (strrchr(s, '\r')||strrchr(s, '\n')
yuuji@1 257 ||strrchr(s, ' ')||strrchr(s, '\t'))) {
yuuji@1 258 *(s+strlen(s)-1) = '\0';
yuuji@1 259 }
yuuji@1 260 while (*s && (*s == '\t' || *s == ' ')) s++;
yuuji@1 261 if (!strncmp(s, dom, strlen(s))) { /* matches with local domain */
yuuji@1 262 int len = dom-account-1;
yuuji@1 263 p = (char*)malloc(len+1);
yuuji@1 264 memset(p, '\0', len+1);
yuuji@1 265 strncpy(p, account, len);
yuuji@1 266 return p;
yuuji@1 267 }
yuuji@1 268 }
yuuji@1 269 }
yuuji@1 270 return NULL; /* invalid domain */
yuuji@1 271 /* return account; return itself */
yuuji@1 272 }
yuuji@1 273
yuuji@1 274 void apopcall(char **args) {
yuuji@1 275 int i=0, sc=0;
yuuji@1 276 pid_t pid;
yuuji@1 277 char *email="", *suffix="", *pass="", *new="", *new2 = "", *home="";
yuuji@1 278 char buf[BUFSIZ], auth, *user;
yuuji@1 279 FILE *child, *result;
yuuji@1 280 while (args[i][0]) {
yuuji@1 281 /* printf("[%s]<br>\n", args[i]); */
yuuji@1 282 if (!strncmp("email=", args[i], 6)) {
yuuji@1 283 email = args[i]+6;
yuuji@1 284 } else if (!strncmp("suffix=", args[i], 7)) {
yuuji@1 285 suffix = args[i]+7;
yuuji@1 286 } else if (!strncmp("pass=", args[i], 5)) {
yuuji@1 287 pass = args[i]+5;
yuuji@1 288 } else if (!strncmp("new=", args[i], 4)) {
yuuji@1 289 new = args[i]+4;
yuuji@1 290 } else if (!strncmp("new2=", args[i], 5)) {
yuuji@1 291 new2 = args[i]+5;
yuuji@1 292 } else if (!strncmp("auth=", args[i], 5)) {
yuuji@1 293 /* "this" or "base" or "unix" */
yuuji@1 294 auth = args[i][5];
yuuji@1 295 }
yuuji@1 296 i++;
yuuji@1 297 }
yuuji@1 298 /* Make a backup of original e-mail address */
yuuji@1 299 /* user = (char*)malloc(1+strlen(email));
yuuji@1 300 strcpy(user, email);
yuuji@1 301 */
yuuji@1 302 user = conv_virtualdomain(email);
yuuji@1 303 if (NULL == user) {
yuuji@1 304 printf("そのようなドメインは無効です(%s)<br>\n", strchr(email, '@'));
yuuji@1 305 printf("入力したメイルアドレスを確認してやり直してください.<br>\n");
yuuji@1 306 fail();
yuuji@1 307 }
yuuji@1 308 if (strchr(user, XADDR_DELIM)) {
yuuji@1 309 char *p = malloc(1+strlen(user));
yuuji@1 310 char *q = NULL;
yuuji@1 311 struct passwd *pwd;
yuuji@1 312 /* printf("user=[%s]<br>\n", user); */
yuuji@1 313
yuuji@1 314 memset(p, '\0', 1+strlen(user));
yuuji@1 315 strcpy(p, user);
yuuji@1 316 while (!(pwd=getpwnam(p)) && (q=strrchr(p, XADDR_DELIM))) {
yuuji@1 317 fflush(stdout);
yuuji@1 318 *q = '\0';
yuuji@1 319 }
yuuji@1 320 if (pwd && q) {
yuuji@1 321 q = user+(q-p)+1;
yuuji@1 322 user=p;
yuuji@1 323 suffix=q;
yuuji@1 324 }
yuuji@1 325 }
yuuji@1 326 if (user[0] && new[0] && new2[0]) {
yuuji@1 327 int tochild[2], toparent[2];
yuuji@1 328 pid_t pid;
yuuji@1 329 int argc=0;
yuuji@1 330 char **argv;
yuuji@1 331 struct passwd *pswd;
yuuji@1 332 char *pstr;
yuuji@1 333
yuuji@1 334 if (!(pswd=getpwnam(user))) {
yuuji@1 335 printf("Unkown user %s.\n", user);
yuuji@1 336 fflush(stdout);
yuuji@1 337 fail();
yuuji@1 338 }
yuuji@1 339 pstr = pswd->pw_passwd;
yuuji@1 340 #ifdef SHADOW_PASSWD
yuuji@1 341 { struct spwd *ss = getspnam(user);
yuuji@1 342 pstr = (char*)ss->sp_pwdp;
yuuji@1 343 }
yuuji@1 344 #endif
yuuji@1 345 home=pswd->pw_dir;
yuuji@1 346 argv = (char**)calloc(4, sizeof(char*));
yuuji@1 347 argv[argc++] = "apoppasswd";
yuuji@1 348 argv[argc++] = "-s";
yuuji@1 349 argv[argc++] = "-c";
yuuji@1 350 /* if old password does not exist,
yuuji@1 351 then check UNIX password */
yuuji@1 352 #if 0
yuuji@1 353 if (apopfile_existp(home, suffix, pswd->pw_uid)) { /* no apop-ext exists */
yuuji@1 354 /* そのまま */
yuuji@1 355 } else if (apopfile_existp(home, "", pswd->pw_uid)) {/* check base mail password */
yuuji@1 356 argv = (char**)realloc(argv, (argc+2)*sizeof(char*));
yuuji@1 357 argv[argc++] = "-b";
yuuji@1 358 }
yuuji@1 359 #endif
yuuji@1 360 switch (auth) {
yuuji@1 361 case 'b': case 'B':
yuuji@1 362 if (apopfile_existp(home, "", pswd->pw_uid)) {
yuuji@1 363 argv = (char**)realloc(argv, (argc+2)*sizeof(char*));
yuuji@1 364 argv[argc++] = "-b";
yuuji@1 365 } else {
yuuji@1 366 printf("基本アドレスのパスワードファイルがありません<br>\n");
yuuji@1 367 fail();
yuuji@1 368 }
yuuji@1 369 break;
yuuji@1 370 case 'u': case 'U':
yuuji@1 371 if (strcmp(pstr, (char*)crypt(pass, pstr))) {
yuuji@1 372 printf("UNIX Password not correct.<br>\n");
yuuji@1 373 /* printf("[%s]vs.[%s]<br>\n",
yuuji@1 374 pswd->pw_passwd, crypt(pass, pswd->pw_passwd)); */
yuuji@1 375 printf("UNIXパスワードと一致しません.<br>\n");
yuuji@1 376 fflush(stdout);
yuuji@1 377 fail();
yuuji@1 378 }
yuuji@1 379 }
yuuji@1 380
yuuji@1 381 if (strlen(new) < 8 || strlen(new2) < 8) {
yuuji@1 382 printf("New mail password must be more than 7 characters.<br>\n");
yuuji@1 383 printf("メイルパスワードは8文字以上にしてください。<br>\n");
yuuji@1 384 fflush(stdout);
yuuji@1 385 fail();
yuuji@1 386 }
yuuji@1 387 if (suffix[0]) {
yuuji@1 388 argv = (char**)realloc(argv, (argc+3)*sizeof(char*));
yuuji@1 389 argv[argc++] = "-e";
yuuji@1 390 argv[argc++] = suffix;
yuuji@1 391
yuuji@1 392 }
yuuji@1 393 argv[argc++] = NULL;
yuuji@1 394 if (setgid(pswd->pw_gid) || 0 != setuid(pswd->pw_uid)) {
yuuji@1 395 printf("Cannot switch to %s\n", user);
yuuji@1 396 printf("uid=%d, gid=%d<br>\n", pswd->pw_gid, pswd->pw_uid);
yuuji@1 397 printf("メイルパスワード変更サーバの設定不良の可能性があるので<br>\n");
yuuji@1 398 printf("お手数ですがこの画面のコピーを添えてシステム管理者");
yuuji@1 399 printf("まで御連絡下さい。<br>\n");
yuuji@1 400 fflush(stdout);
yuuji@1 401 fail();
yuuji@1 402 }
yuuji@1 403
yuuji@1 404 /* OK, start apopasswd */
yuuji@1 405 if (pipe(tochild)+pipe(toparent)) {
yuuji@1 406 printf("Cannot create pipe\n");
yuuji@1 407 fail();
yuuji@1 408 }
yuuji@1 409 if ((pid=fork()) > 0) {
yuuji@1 410 FILE *child = fdopen(tochild[1], "w");
yuuji@1 411 close(tochild[0]);
yuuji@1 412 close(toparent[1]);
yuuji@1 413 fprintf(child, "PASS %s\nNEW %s\nNEW2 %s\n",
yuuji@1 414 pass, new, new2);
yuuji@1 415 fflush(child);
yuuji@1 416 fclose(child);
yuuji@1 417
yuuji@1 418 } else if (pid == -1) {
yuuji@1 419 printf("Cannot fork\n");
yuuji@1 420 fail();
yuuji@1 421 } else {
yuuji@1 422 char *pe = malloc(6+strlen(pswd->pw_dir));
yuuji@1 423 close(tochild[1]);
yuuji@1 424 close(toparent[0]);
yuuji@1 425 dup2(tochild[0], 0);
yuuji@1 426 dup2(toparent[1], 1);
yuuji@1 427
yuuji@1 428 /* setuid section */
yuuji@1 429
yuuji@1 430 strcpy(pe, "HOME=");
yuuji@1 431 strcat(pe, pswd->pw_dir);
yuuji@1 432 if (putenv(pe)) {
yuuji@1 433 puts("ga-n! arichan gakkari<br>");
yuuji@1 434 }
yuuji@1 435 execv(APOPPASSWD, argv);
yuuji@1 436
yuuji@1 437 /* setuid section ends */
yuuji@1 438 fprintf(stderr, "Cannot exec %s\n", APOPPASSWD);
yuuji@1 439 fail();
yuuji@1 440 }
yuuji@1 441 result = fdopen(toparent[0], "r");
yuuji@1 442 while (fgets(buf, BUFSIZ, result)) {
yuuji@1 443 printf("%s<br>", buf);
yuuji@1 444 fflush(stdout);
yuuji@1 445 if (strstr(buf, "Success!")) {
yuuji@1 446 printf("<br>Mail Password changed successfully!<br>\n");
yuuji@1 447 sc++;
yuuji@1 448 break;
yuuji@1 449 } else if (strstr(buf, "mismatch")) {
yuuji@1 450 printf("二個入れた新パスワードが一致しません.<br>\n");
yuuji@1 451 break;
yuuji@1 452 } else if (strstr(buf, "Illegal")) {
yuuji@1 453 printf("照合用パスワードが違います.<br>--\n");
yuuji@1 454 break;
yuuji@1 455 } else if (strstr(buf, "does not exist")) {
yuuji@1 456 /* try_overwrite(user, pass, new, new2, suffix); */
yuuji@1 457 if (suffix[0]) {
yuuji@1 458 printf("%s-%s", user, suffix);
yuuji@1 459 } else {
yuuji@1 460 printf("%s", user);
yuuji@1 461 }
yuuji@1 462 /* ここは来ないことになった(のはず) */
yuuji@1 463 printf("というメイルアカウントは未作成です<br>\n");
yuuji@1 464 printf("新規に作る場合はOKボタンをクリック\n");
yuuji@1 465 put_form(email, pass, new, new2, suffix, 1, 0, 1);
yuuji@1 466 fflush(stdout);
yuuji@1 467 }
yuuji@1 468 }
yuuji@1 469 fclose(result);
yuuji@1 470 while (wait(0) != pid) {sleep(1);fputc('.', stderr);}
yuuji@1 471 if (sc) success(email); else fail();
yuuji@1 472 } else if (user[0]) {
yuuji@1 473 struct passwd *pw = getpwnam(user);
yuuji@1 474 int auth=0;
yuuji@1 475 if (!pw) {
yuuji@1 476 printf("そのようなユーザはいません %s<br>\n", user);
yuuji@1 477 fail();
yuuji@1 478 }
yuuji@1 479 home=pw->pw_dir;
yuuji@1 480
yuuji@1 481 printf("%s というメイルアドレスの<br>\n", email);
yuuji@1 482 printf("メイル専用パスワードを変更します.<br>\n");
yuuji@1 483 printf("メイルパスワードとUNIXパスワードの違いに気をつけてください.<br>\n");
yuuji@1 484 printf("新パスワードは8文字以上にしてください.<br>\n");
yuuji@1 485 printf("New password must be more than or equal to 8 characters.<br>\n");
yuuji@1 486 if (apopfile_existp(home, suffix, pw->pw_uid)) {
yuuji@1 487 auth = 0; /* this password file */
yuuji@1 488 printf("「古いメイルパスワード」には、現在<br>\n");
yuuji@1 489 printf("<tt>%s</tt><br>\n", email);
yuuji@1 490 printf("を読むために指定しているパスワードを入力します。");
yuuji@1 491 } else if (apopfile_existp(home, "", pw->pw_uid)) {
yuuji@1 492 auth = 1; /* basic mail address password */
yuuji@1 493 printf("今回は本人認証として基本メイルアドレスのパスワードを");
yuuji@1 494 printf("入力しますが、新しくパスワードを設定するのは<br>\n");
yuuji@1 495 printf("<tt>%s</tt><br>\n", email);
yuuji@1 496 printf("用のパスワードです。基本メイルアドレスのパスワードは");
yuuji@1 497 printf("変わりませんので注意してください。");
yuuji@1 498 } else {
yuuji@1 499 auth = 2; /* UNIX login */
yuuji@1 500 }
yuuji@1 501 put_form(email, "", "", "", suffix, 0, auth, 0);
yuuji@1 502 footer();
yuuji@1 503 exit(0);
yuuji@1 504 }
yuuji@1 505 printf("user=[%s]\n", user);
yuuji@1 506 }
yuuji@1 507
yuuji@1 508 int main(int argc, char* argv[]) {
yuuji@1 509 char *method = getenv("REQUEST_METHOD");
yuuji@1 510 char **args;
yuuji@1 511 myname = argv[0];
yuuji@1 512 if (method && strcmp(method, "POST") != 0) {
yuuji@1 513 printf("This program should be used in method:POST.\n");
yuuji@1 514 fail();
yuuji@1 515 }
yuuji@1 516 printf("Content-type: text/html; charset=EUC-JP\n\n");
yuuji@1 517 printf("<html>\n<head><title>Change Password</title></head>\n");
yuuji@1 518 printf("<body style=\"background: #f0ffff;\">\n");
yuuji@1 519 if (getenv("SSL_CIPHER") && getenv("SSL_PROTOCOL")) {
yuuji@1 520 args = decode_post();
yuuji@1 521 apopcall(args);
yuuji@1 522 } else {
yuuji@1 523 printf("This program can be used only via SSL connection.<br>\n");
yuuji@1 524 printf("このユーティリティはSSL接続時のみ有効です.<br>\n");
yuuji@1 525 }
yuuji@1 526 }
yuuji@4 527 #include <stdio.h>
yuuji@4 528 #include <stdlib.h>
yuuji@4 529 #include <string.h>
yuuji@4 530 #include <unistd.h>
yuuji@4 531 #include <sys/types.h>
yuuji@4 532 #include <sys/wait.h>
yuuji@4 533 #include <sys/stat.h>
yuuji@4 534 #include <pwd.h>
yuuji@4 535 #ifdef SHADOW_PASSWD
yuuji@4 536 #include <shadow.h>
yuuji@4 537 #endif
yuuji@4 538
yuuji@4 539 #ifndef APOPPASSWD
yuuji@4 540 #define APOPPASSWD "/usr/local/bin/apoppasswd"
yuuji@4 541 #endif
yuuji@4 542 #ifndef APOPFILEBASE
yuuji@4 543 #define APOPFILEBASE ".apop"
yuuji@4 544 #endif
yuuji@4 545 #ifndef XADDR_DELIM
yuuji@4 546 #define XADDR_DELIM ('-')
yuuji@4 547 #endif
yuuji@4 548
yuuji@4 549 char *myname;
yuuji@4 550
yuuji@4 551 int ishexa(int c) {
yuuji@4 552 strchr("0123456789ABCDFabcdef", c) ? 1 : 0;
yuuji@4 553 }
yuuji@4 554
yuuji@4 555 put_form(email, pass, new, new2, suffix, hidden, auth, force)
yuuji@4 556 char *email, *pass, *new, *new2, *suffix;
yuuji@4 557 int hidden, auth, force;
yuuji@4 558 /* auth = 0: old password
yuuji@4 559 1: base addresse's mail password
yuuji@4 560 2: unix password */
yuuji@4 561 {
yuuji@4 562 char *authtype[] = {"old", "base", "unix"};
yuuji@4 563 char *var[] = {"email", "pass", "new", "new2", "auth", ""};
yuuji@4 564 char *val[] = {email, pass, new, new2, authtype[auth]};
yuuji@4 565 char *prm[] = {"", /* "ユーザ名", */
yuuji@4 566 auth ?
yuuji@4 567 ((auth==1)
yuuji@4 568 ? "基本メイルアドレス用パスワード<br>Password for Basic Mail address"
yuuji@4 569 : "UNIXログインパスワード<br>UNIX login Password")
yuuji@4 570 : "古いメイルパスワード<br>Old Mail Password",
yuuji@4 571 "新しいメイルパスワード<br>New Mail Password",
yuuji@4 572 "新パスワードをもう一回(確認)<br>New Mail Password Again",
yuuji@4 573 ""};
yuuji@4 574 int h=0, i;
yuuji@4 575
yuuji@4 576 printf("<form method=POST action\"./%s\">\n", myname);
yuuji@4 577 printf(" <table border=1>\n");
yuuji@4 578 for (i=0; var[i][0]; i++) {
yuuji@4 579 h = hidden || strstr("email,suffix,auth", var[i]);
yuuji@4 580 if (prm[i][0]) {
yuuji@4 581 printf("<tr><td>%s</td><td>", prm[i]);
yuuji@4 582 } else {
yuuji@4 583 }
yuuji@4 584 printf("<input name=%s %svalue=\"%s\" length=40 maxlength=40>\n",
yuuji@4 585 var[i],
yuuji@4 586 h ? "type=hidden "
yuuji@4 587 : (strstr(prm[i], "パスワード") ? "type=password " : "<br>"),
yuuji@4 588 val[i]);
yuuji@4 589 if (!strcmp(var[i], "suffix")) {
yuuji@4 590 /* ここでは suffix を入れさせない方がいいかも */
yuuji@4 591 /* 表向きのメイルアドレスを表示しておく */
yuuji@4 592 printf("%s", email);
yuuji@4 593 /* if (suffix[0]) {
yuuji@4 594 printf("-%s", suffix);
yuuji@4 595 } */
yuuji@4 596 if (auth)
yuuji@4 597 printf("<br>(新規作成:New Account)");
yuuji@4 598 }
yuuji@4 599 if (prm[i][0])
yuuji@4 600 printf("</td></tr>");
yuuji@4 601 printf("\n");
yuuji@4 602 }
yuuji@4 603
yuuji@4 604 printf("</table>\n");
yuuji@4 605 if (force)
yuuji@4 606 printf("<input name=force type=hidden value=ON>\n");
yuuji@4 607 if (auth) {
yuuji@4 608 char *a[] = {"basic", "unix"};
yuuji@4 609 printf("<input type=hidden name=auth value=\"%s\">\n", a[auth-1]);
yuuji@4 610 }
yuuji@4 611 printf("<input name=OK value=OK type=submit>\n");
yuuji@4 612 printf("<input name=RESET value=RESET type=reset>\n");
yuuji@4 613 printf("</form>\n");
yuuji@4 614 fflush(stdout);
yuuji@4 615 }
yuuji@4 616
yuuji@4 617 char *decode(char *code) {
yuuji@4 618 int l=1+strlen(code);
yuuji@4 619 int i, c, d;
yuuji@4 620 char *ret = (char*)malloc(l*sizeof(char));
yuuji@4 621 char *p = code;
yuuji@4 622 memset(ret, 0, l);
yuuji@4 623 for (i=0; i<strlen(code); i++) {
yuuji@4 624 if (code[i] == '+') code[i] = ' ';
yuuji@4 625 }
yuuji@4 626 while (code[0] && (p=strchr(code, '%'))
yuuji@4 627 && ishexa(*(p+1)) && ishexa(*(p+2))) {
yuuji@4 628 *(p++) = '\0';
yuuji@4 629 strncat(ret, code, l);
yuuji@4 630 c = (islower(*p) ? toupper(*p) : *p) - '0';
yuuji@4 631 p++;
yuuji@4 632 d = (islower(*p) ? toupper(*p) : *p) - '0';
yuuji@4 633 if (c > 9) c -= ('A'-'9'-1);
yuuji@4 634 if (d > 9) d -= ('A'-'9'-1);
yuuji@4 635 ret[strlen(ret)] = c*16+d;
yuuji@4 636 code = p+1;
yuuji@4 637 }
yuuji@4 638 if (code[0]) strncat(ret, code, l);
yuuji@4 639 return ret;
yuuji@4 640 }
yuuji@4 641
yuuji@4 642 #define BSIZE 8192
yuuji@4 643 char **decode_post() {
yuuji@4 644 char *buf = (char*)malloc(BSIZE*sizeof(char));
yuuji@4 645 char **post, *p = buf;
yuuji@4 646 int n=0, i;
yuuji@4 647 post = (char**)calloc(1, sizeof(char*));
yuuji@4 648 *buf = '\0';
yuuji@4 649 fgets(buf, BSIZE, stdin);
yuuji@4 650 if (strchr("\n\r", buf[strlen(buf)-1])) /* chop */
yuuji@4 651 buf[strlen(buf)-1] = '\0';
yuuji@4 652 while (buf[0] && NULL != (p=strchr(buf, '&'))) {
yuuji@4 653 *p = '\0';
yuuji@4 654 post[n] = (char*)malloc((p-buf+1)*sizeof(char));
yuuji@4 655 strcpy(post[n], buf);
yuuji@4 656 n++;
yuuji@4 657 post = (char**)realloc(post, (1+n)*sizeof(char*));
yuuji@4 658 buf = 1+p;
yuuji@4 659 }
yuuji@4 660 if (buf[0]) post[n++] = buf;
yuuji@4 661 /* decode URL encoded */
yuuji@4 662 for (i=0; i < n; i++) {
yuuji@4 663 char *p;
yuuji@4 664 p=post[i];
yuuji@4 665 post[i] = decode(p);
yuuji@4 666 }
yuuji@4 667 post[i] = ""; /* terminator */
yuuji@4 668 return post;
yuuji@4 669 }
yuuji@4 670
yuuji@4 671 void footer() {
yuuji@4 672 puts("</body>\n</html>");
yuuji@4 673 fflush(stdout);
yuuji@4 674 }
yuuji@4 675
yuuji@4 676 void fail() {
yuuji@4 677 printf("パスワード更新に失敗しました<br>\n");
yuuji@4 678 printf("<a href=\"./\">やり直し</a><br>\n");
yuuji@4 679 footer();
yuuji@4 680 exit(1);
yuuji@4 681 }
yuuji@4 682 void success(char *email) {
yuuji@4 683 printf("<hr>メイルアカウント %s 用のパスワード更新は完了しました。<br>\n",
yuuji@4 684 email);
yuuji@4 685 footer();
yuuji@4 686 exit(0);
yuuji@4 687 }
yuuji@4 688
yuuji@4 689 int apopfile_existp(char *home, char *suffix, uid_t uid) {
yuuji@4 690 struct stat st;
yuuji@4 691 int s;
yuuji@4 692 int len = strlen(home) + 1
yuuji@4 693 + strlen(APOPFILEBASE) + strlen(suffix) + 3;
yuuji@4 694 char *apopfile = (char*)malloc(len);
yuuji@4 695 if (suffix[0]) {
yuuji@4 696 snprintf(apopfile, len, "%s/%s%c%s%c",
yuuji@4 697 home, APOPFILEBASE, XADDR_DELIM, suffix, 0);
yuuji@4 698 } else {
yuuji@4 699 snprintf(apopfile, len, "%s/%s%c", home, APOPFILEBASE, 0);
yuuji@4 700 }
yuuji@4 701 seteuid(uid);
yuuji@4 702 s = stat(apopfile, &st);
yuuji@4 703 seteuid(0);
yuuji@4 704 memset(apopfile, '\0', strlen(apopfile));
yuuji@4 705 free(apopfile);
yuuji@4 706 return !s;
yuuji@4 707 }
yuuji@4 708
yuuji@4 709 #ifndef QMAILCONTROL
yuuji@4 710 # define QMAILCONTROL "/var/qmail/control"
yuuji@4 711 #endif
yuuji@4 712 #ifndef MAILTMPLEN
yuuji@4 713 # define MAILTMPLEN 1024
yuuji@4 714 #endif
yuuji@4 715
yuuji@4 716 /* Convert virtual domain user
yuuji@4 717 */
yuuji@4 718 char* conv_virtualdomain(char *account) {
yuuji@4 719 char *dom = strchr(account, '@'), *p;
yuuji@4 720 char vd[MAILTMPLEN+1], rewrite[MAILTMPLEN+1], previous[MAILTMPLEN+1];
yuuji@4 721 FILE *vdfd;
yuuji@4 722 int match=0;
yuuji@4 723 char buf[MAILTMPLEN+1], *s;
yuuji@4 724 snprintf(vd, MAILTMPLEN, "%s/%s", QMAILCONTROL, "virtualdomains");
yuuji@4 725 if (NULL == dom) return account;
yuuji@4 726 dom++; /* set position of domain part beginning */
yuuji@4 727 if (dom && NULL != (vdfd = fopen (vd, "r"))) {
yuuji@4 728 int l = strlen(dom);
yuuji@4 729 int L = strlen(account);
yuuji@4 730 while ((s=fgets(buf, MAILTMPLEN, vdfd))) {
yuuji@4 731 if (p=strchr(s, '#'))
yuuji@4 732 *p = '\0'; /* zap comments */
yuuji@4 733 if (!strchr(buf, ':'))
yuuji@4 734 continue;
yuuji@4 735 while (s && (strrchr(s, '\n') || strrchr(s, '\r') || strrchr(s, ' ')))
yuuji@4 736 s[strlen(s)-1] = '\0';
yuuji@4 737 if (!strncmp(account, s, L) && s[L] == ':' && s[L+1]) { /* user matches */
yuuji@4 738 match = 3;
yuuji@4 739 snprintf(rewrite, MAILTMPLEN, "%s-%s", s+L+1, account);
yuuji@4 740 break;
yuuji@4 741 }
yuuji@4 742 if (!strncmp(dom, s, l) && s[l] == ':' && s[l+1]) { /* domain matches */
yuuji@4 743 match = 2;
yuuji@4 744 snprintf(rewrite, MAILTMPLEN, "%s%c%s", s+l+1, XADDR_DELIM, account);
yuuji@4 745 continue;
yuuji@4 746 }
yuuji@4 747 if (match < 2 && s[0] == '.') { /* if domain described in wildcard */
yuuji@4 748 if (p=strchr(s, ':')) {
yuuji@4 749 *p = '\0';
yuuji@4 750 if (!strcmp(dom+(strlen(dom)-strlen(s)), s)) {
yuuji@4 751 if (match == 0
yuuji@4 752 || strlen(previous) < strlen(s)) {
yuuji@4 753 match = 1;
yuuji@4 754 strncpy(previous, s, MAILTMPLEN);
yuuji@4 755 snprintf(rewrite, MAILTMPLEN, "%s%c%s", p+1, XADDR_DELIM, account);
yuuji@4 756 }
yuuji@4 757 }
yuuji@4 758 }
yuuji@4 759 }
yuuji@4 760 }
yuuji@4 761 fclose(vdfd);
yuuji@4 762 if (match) {
yuuji@4 763 p = strchr(rewrite, '@');
yuuji@4 764 /* fprintf(stderr, "m=%d, rwr=[%s]\n", match, rewrite); */
yuuji@4 765 if (p) {
yuuji@4 766 *p = '\0';
yuuji@4 767 }
yuuji@4 768 /* fprintf(stderr, "rwr=[%s]\n", rewrite); */
yuuji@4 769 s = malloc(strlen(rewrite)+1);
yuuji@4 770 strncpy(s, rewrite, strlen(rewrite)+1);
yuuji@4 771 memset(vd, 0, sizeof(vd));
yuuji@4 772 memset(rewrite, 0, sizeof(rewrite));
yuuji@4 773 memset(previous, 0, sizeof(previous));
yuuji@4 774 return s;
yuuji@4 775 }
yuuji@4 776 }
yuuji@4 777 /* Then, compare with locals */
yuuji@4 778 snprintf(vd, MAILTMPLEN, "%s/%s", QMAILCONTROL, "locals");
yuuji@4 779 if (NULL != (vdfd=fopen(vd, "r"))) {
yuuji@4 780 while (s=fgets(buf, MAILTMPLEN, vdfd)) {
yuuji@4 781 if (p=strchr(s, '#')) *p = '\0'; /* zap after comment mark # */
yuuji@4 782 while (*s && (strrchr(s, '\r')||strrchr(s, '\n')
yuuji@4 783 ||strrchr(s, ' ')||strrchr(s, '\t'))) {
yuuji@4 784 *(s+strlen(s)-1) = '\0';
yuuji@4 785 }
yuuji@4 786 while (*s && (*s == '\t' || *s == ' ')) s++;
yuuji@4 787 if (!strncmp(s, dom, strlen(s))) { /* matches with local domain */
yuuji@4 788 int len = dom-account-1;
yuuji@4 789 p = (char*)malloc(len+1);
yuuji@4 790 memset(p, '\0', len+1);
yuuji@4 791 strncpy(p, account, len);
yuuji@4 792 return p;
yuuji@4 793 }
yuuji@4 794 }
yuuji@4 795 }
yuuji@4 796 return NULL; /* invalid domain */
yuuji@4 797 /* return account; return itself */
yuuji@4 798 }
yuuji@4 799
yuuji@4 800 void apopcall(char **args) {
yuuji@4 801 int i=0, sc=0;
yuuji@4 802 pid_t pid;
yuuji@4 803 char *email="", *suffix="", *pass="", *new="", *new2 = "", *home="";
yuuji@4 804 char buf[BUFSIZ], auth, *user;
yuuji@4 805 FILE *child, *result;
yuuji@4 806 while (args[i][0]) {
yuuji@4 807 /* printf("[%s]<br>\n", args[i]); */
yuuji@4 808 if (!strncmp("email=", args[i], 6)) {
yuuji@4 809 email = args[i]+6;
yuuji@4 810 } else if (!strncmp("suffix=", args[i], 7)) {
yuuji@4 811 suffix = args[i]+7;
yuuji@4 812 } else if (!strncmp("pass=", args[i], 5)) {
yuuji@4 813 pass = args[i]+5;
yuuji@4 814 } else if (!strncmp("new=", args[i], 4)) {
yuuji@4 815 new = args[i]+4;
yuuji@4 816 } else if (!strncmp("new2=", args[i], 5)) {
yuuji@4 817 new2 = args[i]+5;
yuuji@4 818 } else if (!strncmp("auth=", args[i], 5)) {
yuuji@4 819 /* "this" or "base" or "unix" */
yuuji@4 820 auth = args[i][5];
yuuji@4 821 }
yuuji@4 822 i++;
yuuji@4 823 }
yuuji@4 824 /* Make a backup of original e-mail address */
yuuji@4 825 /* user = (char*)malloc(1+strlen(email));
yuuji@4 826 strcpy(user, email);
yuuji@4 827 */
yuuji@4 828 user = conv_virtualdomain(email);
yuuji@4 829 if (NULL == user) {
yuuji@4 830 printf("そのようなドメインは無効です(%s)<br>\n", strchr(email, '@'));
yuuji@4 831 printf("入力したメイルアドレスを確認してやり直してください.<br>\n");
yuuji@4 832 fail();
yuuji@4 833 }
yuuji@4 834 if (strchr(user, XADDR_DELIM)) {
yuuji@4 835 char *p = malloc(1+strlen(user));
yuuji@4 836 char *q = NULL;
yuuji@4 837 struct passwd *pwd;
yuuji@4 838 /* printf("user=[%s]<br>\n", user); */
yuuji@4 839
yuuji@4 840 memset(p, '\0', 1+strlen(user));
yuuji@4 841 strcpy(p, user);
yuuji@4 842 while (!(pwd=getpwnam(p)) && (q=strrchr(p, XADDR_DELIM))) {
yuuji@4 843 fflush(stdout);
yuuji@4 844 *q = '\0';
yuuji@4 845 }
yuuji@4 846 if (pwd && q) {
yuuji@4 847 q = user+(q-p)+1;
yuuji@4 848 user=p;
yuuji@4 849 suffix=q;
yuuji@4 850 }
yuuji@4 851 }
yuuji@4 852 if (user[0] && new[0] && new2[0]) {
yuuji@4 853 int tochild[2], toparent[2];
yuuji@4 854 pid_t pid;
yuuji@4 855 int argc=0;
yuuji@4 856 char **argv;
yuuji@4 857 struct passwd *pswd;
yuuji@4 858 char *pstr;
yuuji@4 859
yuuji@4 860 if (!(pswd=getpwnam(user))) {
yuuji@4 861 printf("Unkown user %s.\n", user);
yuuji@4 862 fflush(stdout);
yuuji@4 863 fail();
yuuji@4 864 }
yuuji@4 865 pstr = pswd->pw_passwd;
yuuji@4 866 #ifdef SHADOW_PASSWD
yuuji@4 867 { struct spwd *ss = getspnam(user);
yuuji@4 868 pstr = (char*)ss->sp_pwdp;
yuuji@4 869 }
yuuji@4 870 #endif
yuuji@4 871 home=pswd->pw_dir;
yuuji@4 872 argv = (char**)calloc(4, sizeof(char*));
yuuji@4 873 argv[argc++] = "apoppasswd";
yuuji@4 874 argv[argc++] = "-s";
yuuji@4 875 argv[argc++] = "-c";
yuuji@4 876 /* if old password does not exist,
yuuji@4 877 then check UNIX password */
yuuji@4 878 #if 0
yuuji@4 879 if (apopfile_existp(home, suffix, pswd->pw_uid)) { /* no apop-ext exists */
yuuji@4 880 /* そのまま */
yuuji@4 881 } else if (apopfile_existp(home, "", pswd->pw_uid)) {/* check base mail password */
yuuji@4 882 argv = (char**)realloc(argv, (argc+2)*sizeof(char*));
yuuji@4 883 argv[argc++] = "-b";
yuuji@4 884 }
yuuji@4 885 #endif
yuuji@4 886 switch (auth) {
yuuji@4 887 case 'b': case 'B':
yuuji@4 888 if (apopfile_existp(home, "", pswd->pw_uid)) {
yuuji@4 889 argv = (char**)realloc(argv, (argc+2)*sizeof(char*));
yuuji@4 890 argv[argc++] = "-b";
yuuji@4 891 } else {
yuuji@4 892 printf("基本アドレスのパスワードファイルがありません<br>\n");
yuuji@4 893 fail();
yuuji@4 894 }
yuuji@4 895 break;
yuuji@4 896 case 'u': case 'U':
yuuji@4 897 if (strcmp(pstr, (char*)crypt(pass, pstr))) {
yuuji@4 898 printf("UNIX Password not correct.<br>\n");
yuuji@4 899 /* printf("[%s]vs.[%s]<br>\n",
yuuji@4 900 pswd->pw_passwd, crypt(pass, pswd->pw_passwd)); */
yuuji@4 901 printf("UNIXパスワードと一致しません.<br>\n");
yuuji@4 902 fflush(stdout);
yuuji@4 903 fail();
yuuji@4 904 }
yuuji@4 905 }
yuuji@4 906
yuuji@4 907 if (strlen(new) < 8 || strlen(new2) < 8) {
yuuji@4 908 printf("New mail password must be more than 7 characters.<br>\n");
yuuji@4 909 printf("メイルパスワードは8文字以上にしてください。<br>\n");
yuuji@4 910 fflush(stdout);
yuuji@4 911 fail();
yuuji@4 912 }
yuuji@4 913 if (suffix[0]) {
yuuji@4 914 argv = (char**)realloc(argv, (argc+3)*sizeof(char*));
yuuji@4 915 argv[argc++] = "-e";
yuuji@4 916 argv[argc++] = suffix;
yuuji@4 917
yuuji@4 918 }
yuuji@4 919 argv[argc++] = NULL;
yuuji@4 920 if (setgid(pswd->pw_gid) || 0 != setuid(pswd->pw_uid)) {
yuuji@4 921 printf("Cannot switch to %s\n", user);
yuuji@4 922 printf("uid=%d, gid=%d<br>\n", pswd->pw_gid, pswd->pw_uid);
yuuji@4 923 printf("メイルパスワード変更サーバの設定不良の可能性があるので<br>\n");
yuuji@4 924 printf("お手数ですがこの画面のコピーを添えてシステム管理者");
yuuji@4 925 printf("まで御連絡下さい。<br>\n");
yuuji@4 926 fflush(stdout);
yuuji@4 927 fail();
yuuji@4 928 }
yuuji@4 929
yuuji@4 930 /* OK, start apopasswd */
yuuji@4 931 if (pipe(tochild)+pipe(toparent)) {
yuuji@4 932 printf("Cannot create pipe\n");
yuuji@4 933 fail();
yuuji@4 934 }
yuuji@4 935 if ((pid=fork()) > 0) {
yuuji@4 936 FILE *child = fdopen(tochild[1], "w");
yuuji@4 937 close(tochild[0]);
yuuji@4 938 close(toparent[1]);
yuuji@4 939 fprintf(child, "PASS %s\nNEW %s\nNEW2 %s\n",
yuuji@4 940 pass, new, new2);
yuuji@4 941 fflush(child);
yuuji@4 942 fclose(child);
yuuji@4 943
yuuji@4 944 } else if (pid == -1) {
yuuji@4 945 printf("Cannot fork\n");
yuuji@4 946 fail();
yuuji@4 947 } else {
yuuji@4 948 char *pe = malloc(6+strlen(pswd->pw_dir));
yuuji@4 949 close(tochild[1]);
yuuji@4 950 close(toparent[0]);
yuuji@4 951 dup2(tochild[0], 0);
yuuji@4 952 dup2(toparent[1], 1);
yuuji@4 953
yuuji@4 954 /* setuid section */
yuuji@4 955
yuuji@4 956 strcpy(pe, "HOME=");
yuuji@4 957 strcat(pe, pswd->pw_dir);
yuuji@4 958 if (putenv(pe)) {
yuuji@4 959 puts("ga-n! arichan gakkari<br>");
yuuji@4 960 }
yuuji@4 961 execv(APOPPASSWD, argv);
yuuji@4 962
yuuji@4 963 /* setuid section ends */
yuuji@4 964 fprintf(stderr, "Cannot exec %s\n", APOPPASSWD);
yuuji@4 965 fail();
yuuji@4 966 }
yuuji@4 967 result = fdopen(toparent[0], "r");
yuuji@4 968 while (fgets(buf, BUFSIZ, result)) {
yuuji@4 969 printf("%s<br>", buf);
yuuji@4 970 fflush(stdout);
yuuji@4 971 if (strstr(buf, "Success!")) {
yuuji@4 972 printf("<br>Mail Password changed successfully!<br>\n");
yuuji@4 973 sc++;
yuuji@4 974 break;
yuuji@4 975 } else if (strstr(buf, "mismatch")) {
yuuji@4 976 printf("二個入れた新パスワードが一致しません.<br>\n");
yuuji@4 977 break;
yuuji@4 978 } else if (strstr(buf, "Illegal")) {
yuuji@4 979 printf("照合用パスワードが違います.<br>--\n");
yuuji@4 980 break;
yuuji@4 981 } else if (strstr(buf, "does not exist")) {
yuuji@4 982 /* try_overwrite(user, pass, new, new2, suffix); */
yuuji@4 983 if (suffix[0]) {
yuuji@4 984 printf("%s-%s", user, suffix);
yuuji@4 985 } else {
yuuji@4 986 printf("%s", user);
yuuji@4 987 }
yuuji@4 988 /* ここは来ないことになった(のはず) */
yuuji@4 989 printf("というメイルアカウントは未作成です<br>\n");
yuuji@4 990 printf("新規に作る場合はOKボタンをクリック\n");
yuuji@4 991 put_form(email, pass, new, new2, suffix, 1, 0, 1);
yuuji@4 992 fflush(stdout);
yuuji@4 993 }
yuuji@4 994 }
yuuji@4 995 fclose(result);
yuuji@4 996 while (wait(0) != pid) {sleep(1);fputc('.', stderr);}
yuuji@4 997 if (sc) success(email); else fail();
yuuji@4 998 } else if (user[0]) {
yuuji@4 999 struct passwd *pw = getpwnam(user);
yuuji@4 1000 int auth=0;
yuuji@4 1001 if (!pw) {
yuuji@4 1002 printf("そのようなユーザはいません %s<br>\n", user);
yuuji@4 1003 fail();
yuuji@4 1004 }
yuuji@4 1005 home=pw->pw_dir;
yuuji@4 1006
yuuji@4 1007 printf("%s というメイルアドレスの<br>\n", email);
yuuji@4 1008 printf("メイル専用パスワードを変更します.<br>\n");
yuuji@4 1009 printf("メイルパスワードとUNIXパスワードの違いに気をつけてください.<br>\n");
yuuji@4 1010 printf("新パスワードは8文字以上にしてください.<br>\n");
yuuji@4 1011 printf("New password must be more than or equal to 8 characters.<br>\n");
yuuji@4 1012 if (apopfile_existp(home, suffix, pw->pw_uid)) {
yuuji@4 1013 auth = 0; /* this password file */
yuuji@4 1014 printf("「古いメイルパスワード」には、現在<br>\n");
yuuji@4 1015 printf("<tt>%s</tt><br>\n", email);
yuuji@4 1016 printf("を読むために指定しているパスワードを入力します。");
yuuji@4 1017 } else if (apopfile_existp(home, "", pw->pw_uid)) {
yuuji@4 1018 auth = 1; /* basic mail address password */
yuuji@4 1019 printf("今回は本人認証として基本メイルアドレスのパスワードを");
yuuji@4 1020 printf("入力しますが、新しくパスワードを設定するのは<br>\n");
yuuji@4 1021 printf("<tt>%s</tt><br>\n", email);
yuuji@4 1022 printf("用のパスワードです。基本メイルアドレスのパスワードは");
yuuji@4 1023 printf("変わりませんので注意してください。");
yuuji@4 1024 } else {
yuuji@4 1025 auth = 2; /* UNIX login */
yuuji@4 1026 }
yuuji@4 1027 put_form(email, "", "", "", suffix, 0, auth, 0);
yuuji@4 1028 footer();
yuuji@4 1029 exit(0);
yuuji@4 1030 }
yuuji@4 1031 printf("user=[%s]\n", user);
yuuji@4 1032 }
yuuji@4 1033
yuuji@4 1034 int main(int argc, char* argv[]) {
yuuji@4 1035 char *method = getenv("REQUEST_METHOD");
yuuji@4 1036 char **args;
yuuji@4 1037 myname = argv[0];
yuuji@4 1038 if (method && strcmp(method, "POST") != 0) {
yuuji@4 1039 printf("This program should be used in method:POST.\n");
yuuji@4 1040 fail();
yuuji@4 1041 }
yuuji@4 1042 printf("Content-type: text/html; charset=EUC-JP\n\n");
yuuji@4 1043 printf("<html>\n<head><title>Change Password</title></head>\n");
yuuji@4 1044 printf("<body style=\"background: #f0ffff;\">\n");
yuuji@4 1045 if (getenv("SSL_CIPHER") && getenv("SSL_PROTOCOL")) {
yuuji@4 1046 args = decode_post();
yuuji@4 1047 apopcall(args);
yuuji@4 1048 } else {
yuuji@4 1049 printf("This program can be used only via SSL connection.<br>\n");
yuuji@4 1050 printf("このユーティリティはSSL接続時のみ有効です.<br>\n");
yuuji@4 1051 }
yuuji@4 1052 }

UW-IMAP'd extensions by yuuji