#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include "global.h"
#include "vpopmail.h"
extern int password_len;
extern char verify, *redirect, *password, allowpassword, advertise;
char *dom = NULL, *user = NULL, *fname = NULL, *cemail = NULL, *pass = NULL,
*vpass = NULL;
void go_register(void)
{
int ret = 0;
char *pword = NULL;
dom = cgi_is_var("dom");
fname = cgi_is_var("fname");
user = cgi_is_var("user");
cemail = cgi_is_var("cemail");
if ((!dom) || (!user) || (!fname))
global_error("Misconfigured templates.", 0, 0);
if (!allowpassword) {
if (!cemail)
global_error("Misconfigured templates.", 0, 0);
}
else {
pass = cgi_is_var("pass");
vpass = cgi_is_var("vpass");
if ((!pass) || (!vpass))
global_error("Misconfigured templates.", 0, 0);
}
if (!allowpassword) {
if (password)
pword = password;
else {
pword = gen_pass(password_len);
if (pword == NULL) {
global_warning("Out of resources.");
global_warning("Please wait, and try again.");
t_open(T_REGISTER);
}
}
}
else
pword = pass;
global_par("RP", pword);
global_par("VP", pword);
ret = fields_okay();
if (*dom)
global_par("RD", dom);
if (*user)
global_par("RU", user);
if (*fname)
global_par("RN", fname);
/*
Always do this, because cemail can be optional.
*/
if (cemail)
global_par("CE", cemail);
if ((!(*dom)) || (!(*user)) || (!(*fname))) {
global_warning("Please fill in all fields.");
if (allowpassword)
t_open(T_REGISTER_WITH_PASSWORD);
else
t_open(T_REGISTER);
return;
}
if (allowpassword) {
if ((!(*pass)) || (!(*vpass))) {
global_warning("Please fill in all fields.");
t_open(T_REGISTER_WITH_PASSWORD);
return;
}
if (strcmp(pass, vpass)) {
global_warning("Passwords do not match.");
t_open(T_REGISTER_WITH_PASSWORD);
return;
}
pword = pass;
}
/*
Field checking from above.
*/
if (!ret) {
global_warning("Please fill in all fields.");
if (allowpassword)
t_open(T_REGISTER_WITH_PASSWORD);
else
t_open(T_REGISTER);
}
if (!allowpassword) {
if (!(*cemail)) {
global_warning("Please fill in all fields.");
t_open(T_REGISTER);
return;
}
}
if (strlen(dom) >= 165) {
global_warning("Invalid domain.");
if (allowpassword)
t_open(T_REGISTER_WITH_PASSWORD);
else
t_open(T_REGISTER);
return;
}
if (!(is_domain(dom))) {
global_warning("You may not sign up for that domain.");
global_warning("Please choose another.");
if (allowpassword)
t_open(T_REGISTER_WITH_PASSWORD);
else
t_open(T_REGISTER);
return;
}
if (strlen(user) > 20) {
global_warning("Please supply a shorter username.");
if (allowpassword)
t_open(T_REGISTER_WITH_PASSWORD);
else
t_open(T_REGISTER);
}
ret = add_user(user, dom, pword, fname);
if (ret != VA_SUCCESS) {
/*
This is where we handle the great deal of error
messages vpopmail might throw back at us.
*/
if ((ret == VA_BAD_CHAR) || (ret == VA_ILLEGAL_USERNAME)) {
global_warning("That username is illegal.");
global_warning("Please select another.");
t_open(T_REGISTER);
}
if (ret == VA_USERNAME_EXISTS) {
global_warning("That username is in use.");
global_warning("Please select another.");
t_open(T_REGISTER);
}
/*
These are all the admin's fault.
*/
if (ret <= -3) {
if (ret == VA_BAD_D_DIR)
global_error("Although the domain you requested is available for signup, " \
"this server does not yet support it.", 0, 0);
else
global_error("Unable to add user due to bad permissions.", 0, 0);
}
}
/*
Verify is on
*/
if ((verify == 1) && (cemail) && (*cemail)) {
ret = send_email();
if (ret == 0) {
del_user(user, dom);
/*
Let send_email() set warnings...
global_warning("Out of resources.");
global_warning("Please wait, and try again.");
*/
if (allowpassword)
t_open(T_REGISTER_WITH_PASSWORD);
else
t_open(T_REGISTER);
}
else if (ret == 1) {
field_trigger();
if (redirect) {
printf("Location: %s\n\n", redirect);
return;
}
if (allowpassword)
t_open(T_SUCCESS_WITH_PASSWORD);
else
t_open(T_SUCCESS);
}
else if (ret == 2) {
global_warning("Invalid email address.");
if (allowpassword)
t_open(T_REGISTER_WITH_PASSWORD);
else
t_open(T_REGISTER);
}
else
tfatal();
}
/*
Verify is off
*/
else {
field_trigger();
if (redirect) {
printf("Location: %s\n\n", redirect);
return;
}
if (allowpassword)
t_open(T_SUCCESS_WITH_PASSWORD);
else
t_open(T_SUCCESS);
}
}
int send_email(void)
{
char *p = NULL, *email = NULL, b[500] = { 0 };
int fd0[2] = { 0, 0 }, pid = 0, ret = 0, eret = 0,
cout = 0, cin = 0, pout = 0, pin = 0;
char ch = 0;
/*
Check for weird characters in
current email address.
*/
for (p = cemail; *p; p++) {
if (((*p < '0') || (*p > '9')) &&
((*p < 'a') || (*p > 'z')) &&
((*p < 'A') || (*p > 'Z')) &&
((*p != '-') && (*p != '@') && (*p != '.') && (*p != '_')))
return 2;
}
email = mstrdup(cemail);
for (p = email; *p; p++) {
if (*p == '@') {
*p++ = '\0';
break;
}
}
if (!(*p))
return 2;
ret = check_badhosts(p);
if (ret) {
global_warning("The current email address you provided, and all it's users, have been denied service by this administrator.");
global_warning("Please provide another email address.");
return 0;
}
ret = pipe(fd0);
if (ret == -1) {
global_warning("Out of resources, please try again later.");
return 0;
}
pin = fd0[0];
cout = fd0[1];
ret = pipe(fd0);
if (ret == -1) {
global_warning("Out of resources, please try again later.");
return 0;
}
cin = fd0[0];
pout = fd0[1];
pid = fork();
if (pid == 0) {
/*
Give parent a few seconds to spool it's message.
This may be needed on slower systems, or on systems
which swap it's processes out now and then.
*/
sleep(3);
close(pin);
close(pout);
close(0);
ret = fcntl(cin, F_DUPFD, 0);
if (ret == -1) {
printf("h-DChild descriptor duplication failed\n");
exit(0);
}
close(cin);
close(1);
ret = fcntl(cout, F_DUPFD, 1);
if (ret == -1) {
printf("h-DChild descriptor duplication failed\n");
exit(0);
}
close(cout);
close(2);
ret = fcntl(1, F_DUPFD, 2);
if (ret == -1) {
printf("h-DChild descriptor duplication failed\n");
exit(0);
}
eret = execl("/var/qmail/bin/qmail-remote", "/var/qmail/bin/qmail-remote", p, "register@inter7.com", cemail, NULL);
if (eret == -1)
printf("h-DChild execution failed\n");
exit(0);
}
else if (pid == -1) {
global_warning("Out of resources, please try again later.");
return 0;
}
else if (pid) {
close(cin);
close(cout);
et_open(pout, ET_EMAIL);
if (advertise) {
memset((char *)b, 0, 500);
snprintf(b, 500, "\n" \
"--------------------------------\n" \
"vQregister v%s - www.inter7.com\n" \
"--------------------------------\n",
VQREGISTER_VERSION);
ret = write(pout, (char *)b, strlen(b));
if (ret < strlen(b)) {
del_user(user, dom);
global_warning("Message spool failed");
t_open(T_FAILURE);
}
}
close(pout);
memset((char *)b, 0, 500);
ret = read(pin, (char *)b, 500);
if (ret < 1) {
del_user(user, dom);
global_warning("Message delivery response read failed");
t_open(T_FAILURE);
}
/*
This is where we handle the various
qmail-remote returns.
*/
if ((*b == 'Z') || (*b == 'D')) {
del_user(user, dom);
global_warning(b + 1);
t_open(T_FAILURE);
}
else if ((*b == 'h') || (*b == 's')) {
del_user(user, dom);
global_warning(b + 3);
t_open(T_FAILURE);
}
else {
if ((*(b + 2) == 'D') || (*(b + 2) == 'Z')) {
del_user(user, dom);
global_warning(b + 3);
t_open(T_FAILURE);
}
}
close(pin);
return 1;
}
else
return 3;
}
char *setup_var(char *name, char *tc)
{
char *var = NULL;
var = cgi_is_var(name);
if (var == NULL) {
global_warning("Missing required data");
global_warning(name);
if (allowpassword)
t_open(T_REGISTER_WITH_PASSWORD);
else
t_open(T_REGISTER);
}
global_par(tc, var);
return var;
}
syntax highlighted by Code2HTML, v. 0.9.1