static int maildir_tmpcreate_fd_do(struct maildir_tmpcreate_info *info) { const char *maildir=info->maildir; const char *uniq=info->uniq; const char *hostname=info->hostname; char hostname_buf[256]; char time_buf[NUMBUFSIZE]; char usec_buf[NUMBUFSIZE]; char pid_buf[NUMBUFSIZE]; char len_buf[NUMBUFSIZE+3]; char dev_buf[NUMBUFSIZE]; char ino_buf[NUMBUFSIZE]; struct timeval tv; struct stat stat_buf; int fd; if (!maildir) maildir="."; if (!uniq) uniq=""; if (!hostname || !*hostname) { hostname_buf[sizeof(hostname_buf)-1]=0; if (gethostname(hostname_buf, sizeof(hostname_buf)-1) < 0) strcpy(hostname_buf, "localhost"); hostname=hostname_buf; } gettimeofday(&tv, NULL); libmail_str_time_t(tv.tv_sec, time_buf); libmail_str_time_t(tv.tv_usec, usec_buf); libmail_str_pid_t(getpid(), pid_buf); len_buf[0]=0; if (info->msgsize > 0) { strcpy(len_buf, ",S="); libmail_str_size_t(info->msgsize, len_buf+3); } if (info->tmpname) free(info->tmpname); info->tmpname=malloc(strlen(maildir)+strlen(uniq)+ strlen(hostname)+strlen(time_buf)+ strlen(usec_buf)+ strlen(pid_buf)+strlen(len_buf)+100); if (!info->tmpname) { maildir_tmpcreate_free(info); return -1; } strcpy(info->tmpname, maildir); strcat(info->tmpname, "/tmp/"); strcat(info->tmpname, time_buf); strcat(info->tmpname, ".M"); strcat(info->tmpname, usec_buf); strcat(info->tmpname, "P"); strcat(info->tmpname, pid_buf); if (*uniq) strcat(strcat(info->tmpname, "_"), uniq); strcat(info->tmpname, "."); strcat(info->tmpname, hostname); strcat(info->tmpname, len_buf); if (stat( info->tmpname, &stat_buf) == 0) { maildir_tmpcreate_free(info); errno=EAGAIN; return -1; } if (errno != ENOENT) { maildir_tmpcreate_free(info); if (errno == EAGAIN) errno=EIO; return -1; } if ((fd=maildir_safeopen_stat(info->tmpname, O_CREAT|O_RDWR|O_TRUNC, info->openmode, &stat_buf)) < 0) { maildir_tmpcreate_free(info); return -1; } libmail_strh_dev_t(stat_buf.st_dev, dev_buf); libmail_strh_ino_t(stat_buf.st_ino, ino_buf); if (info->newname) free(info->newname); info->newname=NULL; if (info->curname) free(info->curname); info->curname=NULL; info->newname=malloc(strlen(info->tmpname)+strlen(ino_buf)+ strlen(dev_buf)+3); if (info->newname) { info->curname=malloc(strlen(info->tmpname)+strlen(ino_buf)+ strlen(dev_buf)+3); if (!info->curname) { free(info->newname); info->newname=NULL; } } if (!info->newname) { maildir_tmpcreate_free(info); unlink(info->tmpname); close(fd); if (errno == EAGAIN) errno=EIO; return -1; } strcpy(info->newname, maildir); strcat(info->newname, "/new/"); strcat(info->newname, time_buf); strcat(info->newname, ".M"); strcat(info->newname, usec_buf); strcat(info->newname, "P"); strcat(info->newname, pid_buf); strcat(info->newname, "V"); strcat(info->newname, dev_buf); strcat(info->newname, "I"); strcat(info->newname, ino_buf); if (*uniq) strcat(strcat(info->newname, "_"), uniq); strcat(info->newname, "."); strcat(info->newname, hostname); strcat(info->newname, len_buf); strcpy(info->curname, info->newname); memcpy(info->curname + strlen(maildir)+1, "cur", 3); return fd; }
static char *mkcmdbuf(const char *name, const char *addr, const char *comment, int skeylen, int ekeylen, unsigned expire, char expire_unit, const char *passphrase) { static const char genkey_cmd[]= "Key-Type: DSA\n" "Key-Length: %s\n" "Subkey-Type: ELG-E\n" "Subkey-Length: %s\n" "Name-Real: %s\n" "%s%s%s" "%s%s%s" "Name-Email: %s\n" "Expire-Date: %s\n" "%%commit\n"; static const char comment1[]="Name-Comment: "; static const char comment2[]="\n"; static const char passphrase1[]="Passphrase: "; static const char passphrase2[]="\n"; char skl_buf[NUMBUFSIZE]; char kl_buf[NUMBUFSIZE]; char exp_buf[NUMBUFSIZE+1]; char *p; libmail_str_size_t(skeylen, skl_buf); libmail_str_size_t(ekeylen, kl_buf); if (expire == 0) { strcpy(exp_buf, "0"); } else { char b[2]; b[0]=expire_unit; b[1]=0; strcat(libmail_str_size_t(expire, exp_buf), b); } p=malloc(256+strlen(kl_buf)+strlen(skl_buf)+strlen(exp_buf) +strlen(name)+strlen(addr)+strlen(comment) +strlen(passphrase)); if (!p) return (NULL); while (*comment == ' ' || *comment == '\t') ++comment; sprintf(p, genkey_cmd, skl_buf, kl_buf, name, *comment ? comment1:"", comment, *comment ? comment2:"", *passphrase ? passphrase1:"", passphrase, *passphrase ? passphrase2:"", addr, exp_buf); return (p); }
int msgq::tmpscan() { int found=0; time(¤t_time); DIR *tmpdir=opendir(TMPDIR); if (!tmpdir) clog_msg_errno(); struct dirent *de; std::string subdir; std::string ctlfile, datfile, newctlfile, newdatfile; struct stat stat_buf; std::string qdir, qname; while ((de=readdir(tmpdir)) != 0) { const char *p; for (p=de->d_name; *p; p++) if (!isdigit((int)(unsigned char)*p)) break; if (*p) continue; // Subdirs must be named all digits subdir=TMPDIR "/"; subdir += de->d_name; DIR *subde=opendir(subdir.c_str()); while ((de=readdir(subde)) != 0 && found < 100) { if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) continue; ctlfile=subdir; ctlfile += '/'; ctlfile += de->d_name; int i=-1; if (stat(ctlfile.c_str(), &stat_buf)) continue; size_t j=ctlfile.size(); while (j) { if (ctlfile[--j] == '/') break; if (ctlfile[j] == '.') { i=j; break; } } ino_t inum=stat_buf.st_ino; // Cleanup timeout. Should always be sufficiently longer than // the submit timeout set in submit.C via alarm_timeout. if (stat_buf.st_mtime < current_time - 48 * 60 * 60) { if (de->d_name[0] == 'D') { datfile=subdir + "/C" + (de->d_name+1); if (stat(datfile.c_str(), &stat_buf) == 0) continue; // Wait until the C file is // purged // Be carefull with Cnnnn.x files, because // Cnnnn.1 is used to hold submission of all // of them. A race condition can leave // Cnnnn.1 in a submittable state, so if it // is removed, other copies of this message // can become submittable, during a very small // window. } else if (de->d_name[0] == 'C' && i >= 0) { // This race condition is handled simply // by not removing Cxxxxx.n if Cxxxxx.n+1 // exists. char nbuf[NUMBUFSIZE]; datfile=ctlfile.substr(0, i); size_t n=atoi( ctlfile.c_str()+i+1); ++n; datfile += '.'; datfile += libmail_str_size_t(n, nbuf); if (stat(datfile.c_str(), &stat_buf) == 0) continue; // Wait until the C.1 file is // purged unlink(ctlfile.c_str()); ctlfile=subdir + "/D" + (de->d_name+1); /* FALLTHRU */ } unlink(ctlfile.c_str()); continue; } if (de->d_name[0] != 'C') continue; if (i >= 0) { datfile=ctlfile.substr(0, i); datfile += ".1"; if (ctlfile == datfile || stat(datfile.c_str(), &stat_buf) == 0) continue; } datfile=subdir + "/D" + (de->d_name+1); newdatfile=qmsgsdatname(inum); newctlfile=qmsgsctlname(inum); struct ctlfile ctf; if ((access(datfile.c_str(), 0) == 0 && access(newdatfile.c_str(), 0) == 0) || access(newctlfile.c_str(), 0) == 0 || ctlfile_openfn(ctlfile.c_str(), &ctf, 0, 0)) { clog_msg_start_err(); clog_msg_str("QUEUE FILE CORRUPTION: inode "); clog_msg_uint(inum); clog_msg_send(); utime(ctlfile.c_str(), 0); // Keep it around continue; } time_t nextattempt=current_time+delaytime; if ((i=ctlfile_searchfirst(&ctf, COMCTLFILE_SUBMITDELAY)) >= 0) nextattempt=current_time+ atoi(ctf.lines[i]+1); qname=qmsgqname(inum, nextattempt); ctlfile_nextattempt(&ctf, nextattempt); if (link(ctlfile.c_str(), qname.c_str())) { mkdir(qmsgqdir(current_time),0755); if (link(ctlfile.c_str(), qname.c_str()) && errno != EEXIST) clog_msg_errno(); } if (rename(datfile.c_str(), newdatfile.c_str())) { mkdir(qmsgsdir(inum), 0755); // We may need to create this dir rename(datfile.c_str(), newdatfile.c_str()); } if (rename(ctlfile.c_str(), newctlfile.c_str())) clog_msg_errno(); for (i=qname.size(); i; ) { if (qname[--i] == '/') break; } qdir=qname.substr(0, i); qname=qname.substr(i+1); ++found; ctlfile_close(&ctf); queuescan3(qdir, qname, de->d_name); } closedir(subde); if (stat(subdir.c_str(), &stat_buf) == 0 && stat_buf.st_mtime < current_time - 2 * 60 * 60) rmdir(subdir.c_str()); // Just give it a try } closedir(tmpdir); return (found); }
int gpgdecode(int in_fd, int out_fd) { char passfd_buf[NUMBUFSIZE]; FILE *fp=passphrasefp(); int in_dup, out_dup; FILE *in_fp, *out_fp; struct libmail_gpg_info gi; char *argvec[2]; int i; gpginiterr(); if ((in_dup=dup(in_fd)) < 0 || (in_fp=fdopen(in_dup, "r")) == NULL) { if (in_dup >= 0) close(in_dup); fclose(fp); enomem(); return 1; } if ((out_dup=dup(out_fd)) < 0 || (out_fp=fdopen(out_dup, "w")) == NULL) { if (out_dup >= 0) close(out_dup); fclose(in_fp); close(in_dup); fclose(fp); enomem(); return 1; } memset(&gi, 0, sizeof(gi)); gi.gnupghome=GPGDIR; if (fp) { gi.passphrase_fd=libmail_str_size_t(fileno(fp), passfd_buf); } gi.input_func= read_fd; gi.input_func_arg= in_fp; gi.output_func= write_fd; gi.output_func_arg= out_fp; gi.errhandler_func= gpg_error_save; gi.errhandler_arg= NULL; argvec[0] = "--no-tty"; argvec[1]=NULL; gi.argc=1; gi.argv=argvec; i=libmail_gpg_decode(LIBMAIL_GPG_UNENCRYPT|LIBMAIL_GPG_CHECKSIGN, &gi); fclose(out_fp); close(out_dup); fclose(in_fp); close(in_dup); if (fp) fclose(fp); if (i) { printf("<div class=\"indent\"><pre style=\"color: red;\">"); sent_gpgerrtxt(); printf("</pre></div>\n"); } return (i); }
int gpgdomsg(int in_fd, int out_fd, const char *signkey, const char *encryptkeys) { char *k=strdup(encryptkeys ? encryptkeys:""); int n; int i; char *p; char **argvec; FILE *passfd=NULL; char passfd_buf[NUMBUFSIZE]; struct libmail_gpg_info gi; int in_dup, out_dup; FILE *in_fp, *out_fp; gpginiterr(); if (!k) { enomem(); return 1; } if ((in_dup=dup(in_fd)) < 0 || (in_fp=fdopen(in_dup, "r")) == NULL) { if (in_dup >= 0) close(in_dup); free(k); enomem(); return 1; } if ((out_dup=dup(out_fd)) < 0 || (out_fp=fdopen(out_dup, "w")) == NULL) { if (out_dup >= 0) close(out_dup); fclose(in_fp); close(in_dup); free(k); enomem(); return 1; } passfd=passphrasefp(); n=0; for (p=k; (p=strtok(p, " ")) != NULL; p=NULL) ++n; argvec=malloc((n * 2 + 22)*sizeof(char *)); if (!argvec) { fclose(out_fp); close(out_dup); fclose(in_fp); close(in_dup); free(k); enomem(); return 1; } memset(&gi, 0, sizeof(gi)); gi.gnupghome=GPGDIR; if (passfd) { gi.passphrase_fd=libmail_str_size_t(fileno(passfd), passfd_buf); } gi.input_func= read_fd; gi.input_func_arg= in_fp; gi.output_func= write_fd; gi.output_func_arg= out_fp; gi.errhandler_func= gpg_error_save; gi.errhandler_arg= NULL; i=0; argvec[i++] = "--no-tty"; if (signkey) { argvec[i++]="--default-key"; argvec[i++]=(char *)signkey; } argvec[i++]="--always-trust"; for (p=strcpy(k, encryptkeys ? encryptkeys:""); (p=strtok(p, " ")) != NULL; p=NULL) { argvec[i++]="-r"; argvec[i++]=p; } argvec[i]=0; gi.argc=i; gi.argv=argvec; i=libmail_gpg_signencode(signkey ? 1:0, n > 0 ? LIBMAIL_GPG_ENCAPSULATE:0, &gi); free(argvec); fclose(out_fp); close(out_dup); fclose(in_fp); close(in_dup); free(k); if (passfd) fclose(passfd); return i; }
int gpgdecode(int in_fd, int out_fd) { pid_t pid; int stderrfd[2]; int rc; if (pipe(stderrfd)) { enomem(); } pid=fork(); if (pid < 0) { close(stderrfd[0]); close(stderrfd[1]); enomem(); } if (pid == 0) { FILE *fp=passphrasefp(); char *argvec[20]; int i; char passfd_buf[NUMBUFSIZE]; close(0); dup(in_fd); close(1); dup(out_fd); close(in_fd); close(out_fd); close(2); dup(stderrfd[1]); close(stderrfd[1]); close(stderrfd[0]); argvec[0]=MIMEGPG; argvec[1]="-c"; argvec[2]="-d"; i=3; if (fp) { argvec[i++]="-p"; argvec[i++]=libmail_str_size_t(fileno(fp), passfd_buf); } argvec[i++]="--"; argvec[i++]="--no-tty"; argvec[i]=0; putenv("GNUPGHOME=" GPGDIR); execv(MIMEGPG, argvec); perror(MIMEGPG); exit(1); } close (stderrfd[1]); rc=wait_mimegpg(pid, stderrfd[0]); if (rc) { printf("<blockquote><pre style=\"color: red;\">"); sent_gpgerrtxt(); printf("</pre></blockquote>\n"); } return (rc); }
int gpgdomsg(int in_fd, int out_fd, const char *signkey, const char *encryptkeys) { char *k=strdup(encryptkeys ? encryptkeys:""); int n; int i; char *p; char **argvec; pid_t pid; int stderrfd[2]; FILE *passfd=NULL; const char *cp; char passfd_buf[NUMBUFSIZE]; if (!k) enomem(); if (pipe(stderrfd)) { free(k); enomem(); } if (*(cp=cgi("passphrase")) != 0) { passfd=tmpfile(); if (passfd) { fprintf(passfd, "%s", cp); if (fflush(passfd) || ferror(passfd) || lseek(fileno(passfd), 0L, SEEK_SET) < 0 || fcntl(fileno(passfd), F_SETFD, 0) < 0) { fclose(passfd); passfd=NULL; } } } n=0; for (p=k; (p=strtok(p, " ")) != NULL; p=NULL) ++n; argvec=malloc((n * 2 + 22)*sizeof(char *)); if (!argvec) { close(stderrfd[0]); close(stderrfd[1]); free(k); enomem(); } i=0; argvec[i++]=MIMEGPG; if (signkey) argvec[i++]="-s"; if (n > 0) argvec[i++]="-E"; if (passfd) { argvec[i++]="-p"; argvec[i++]=libmail_str_size_t(fileno(passfd), passfd_buf); } argvec[i++] = "--"; argvec[i++] = "--no-tty"; if (signkey) { argvec[i++]="--default-key"; argvec[i++]=(char *)signkey; } argvec[i++]="--always-trust"; for (p=strcpy(k, encryptkeys ? encryptkeys:""); (p=strtok(p, " ")) != NULL; p=NULL) { argvec[i++]="-r"; argvec[i++]=p; } argvec[i]=0; pid=fork(); if (pid < 0) { free(k); close(stderrfd[0]); close(stderrfd[1]); return (-1); } if (pid == 0) { close(0); dup(in_fd); close(1); dup(out_fd); close(in_fd); close(out_fd); close(2); dup(stderrfd[1]); close(stderrfd[1]); close(stderrfd[0]); putenv("GNUPGHOME=" GPGDIR); execv(argvec[0], argvec); perror("mimegpg"); exit(1); } free(argvec); free(k); close(stderrfd[1]); if (passfd) fclose(passfd); return ( wait_mimegpg(pid, stderrfd[0])); }