1 // Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
2 //
3 // This program is free software; you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation; either version 2 of the License, or
6 // (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16
17 #include <config.h>
18 #include <stdlib.h>
19 #include <time.h>
20 #include "fdbuf/fdbuf.h"
21 #include "misc/passwdfn.h"
22 #include "mystring/mystring.h"
23 #include "config/configrc.h"
24 #include "misc/pwcrypt.h"
25 #include "vcommand.h"
26 #include "cli++/cli++.h"
27
28 const char* cli_program = "vadduser";
29 const char* cli_help_prefix = "Add a user to a virtual domain\n";
30 const char* cli_help_suffix = "";
31 const char* cli_args_usage = "USERNAME [ALIAS1 ...]\n"
32 "or vaddalias USERNAME [ALIAS1 ...]";
33 const int cli_args_min = 1;
34 const int cli_args_max = -1;
35
36 static const char* o_userdir = 0;
37 static cli_stringlist* o_forwards = 0;
38 static const char* o_personal = 0;
39 static int o_softquota = 0;
40 static int o_hardquota = 0;
41 static int o_msgsize = 0;
42 static int o_msgcount = 0;
43 static int o_expiry = 0;
44 static int o_password = true;
45 static int o_hasmailbox = true;
46 static int o_quiet = false;
47 static const char* o_pwcrypt = 0;
48
49 // This program is used to set up a user within a virtual host.
50 // If this program is reading from a tty,
51 // it will then ask for a password (twice, to make sure you typed it in
52 // correctly), otherwise it will read the password from the input with no
53 // prompting.
54 // It will then
55 // add the user to the virtual password table in the current
56 // directory and create a mail directory for the new user.
57 // It will also add an entry for each of the named aliases.
58
59 cli_option cli_options[] = {
60 { 'c', "msgcount", cli_option::integer, 0, &o_msgcount,
61 "Set the user's message count limit", 0 },
62 { 'D', "no-mailbox", cli_option::flag, false, &o_hasmailbox,
63 "Do not create a mailbox for this user", "true for vaddalias" },
64 { 'd', "directory", cli_option::string, 0, &o_userdir,
65 "Set the path to the user's mailbox", 0 },
66 // Set the path to the user's mailbox.
67 // Note that this directory is unconditionally prefixed with "./".
68 { 'e', "expiry", cli_option::integer, 0, &o_expiry,
69 "Set the account's expiry time (in seconds)", 0 },
70 { 'f', "forward", cli_option::stringlist, 0, &o_forwards,
71 "Add a forwarding address to this user", 0 },
72 // Add a forwarding address to this user (this may be used multiple times).
73 { 0, "password", cli_option::string, 0, &o_pwcrypt,
74 "Encrypted password", "asking for a password" },
75 { 'P', "no-password", cli_option::flag, false, &o_password,
76 "Do not ask for a password", 0 },
77 // Do not ask for a password,
78 // and instead set the pass phrase field to an unusable value.
79 { 'p', "personal", cli_option::string, 0, &o_personal,
80 "Set the user's personal information", 0 },
81 { 'Q', "hardquota", cli_option::integer, 0, &o_hardquota,
82 "Set the user's hard quota (in bytes)", 0 },
83 { 'q', "softquota", cli_option::integer, 0, &o_softquota,
84 "Set the user's soft quota (in bytes)", 0 },
85 { 0, "quiet", cli_option::flag, true, &o_quiet,
86 "Suppress all status messages", 0 },
87 { 'z', "msgsize", cli_option::integer, 0, &o_msgsize,
88 "Set the user's message size limit (in bytes)", 0 },
89 {0}
90 };
91
92 // RETURN VALUE
93 //
94 // 0 if all steps were successful, non-zero otherwise.
95 // If any of the steps fail, a diagnostic message is printed.
96
97 // SEE ALSO
98 //
99 // vsetup(1)
100
101 // NOTES
102 // You must have either created the users subdirectory by hand or run the
103 // F<vsetup> program before using this program.
104 //
105 // This program expects the environment variable C<HOME> to be set, and
106 // executes a change directory to the contents of it before starting. It
107 // is also required that you change user to the domain owner before using
108 // these utilities.
109
list2str(cli_stringlist * list)110 mystring list2str(cli_stringlist* list)
111 {
112 if(!list)
113 return 0;
114 mystring result = list->string;
115 list = list->next;
116 while(list) {
117 result = result + mystring::NUL + list->string;
118 list = list->next;
119 }
120 return result;
121 }
122
make_user(const mystring & name,const mystring & passcode)123 vpwentry* make_user(const mystring& name, const mystring& passcode)
124 {
125 mystring dir;
126 if(o_userdir)
127 dir = o_userdir;
128 else
129 dir = domain.userdir(name);
130 dir = "./" + dir;
131
132 for(cli_stringlist* node = o_forwards; node; node = node->next) {
133 response r = domain.validate_forward(node->string);
134 if(!r) {
135 if(!o_quiet)
136 ferr << argv0base << ": invalid forwarding address:\n "
137 << r.msg << endl;
138 exit(1);
139 }
140 }
141
142 vpwentry* vpw = new vpwentry(name.lower(), passcode, dir,
143 list2str(o_forwards), o_hasmailbox);
144 vpw->personal = o_personal;
145 vpw->hardquota = o_hardquota;
146 vpw->softquota = o_softquota;
147 vpw->msgcount = o_msgcount;
148 vpw->msgsize = o_msgsize;
149 vpw->expiry = o_expiry;
150 //vpw->data = list2str(o_extra);
151
152 return vpw;
153 }
154
add_user(const mystring & user)155 void add_user(const mystring& user)
156 {
157 if(!domain.exists(user)) {
158 mystring passcode;
159 if(o_pwcrypt)
160 passcode = o_pwcrypt;
161 else if(o_password) {
162 mystring passwd = getpasswd(argv0base);
163 if(passwd.length() == 0)
164 exit(1);
165 passcode = pwcrypt(passwd);
166 }
167 else
168 passcode = "*";
169 vpwentry* vpw = make_user(user, passcode);
170 response resp = domain.set(vpw, true);
171 delete vpw;
172 if(!resp) {
173 if(!o_quiet)
174 ferr << argv0base << ": error adding the virtual user:\n "
175 << resp.msg << endl;
176 exit(1);
177 }
178 }
179 else {
180 ferr << argv0base << ": error: user '" << user << "' already exists."
181 << endl;
182 exit(1);
183 }
184 }
185
add_alias(mystring user,mystring alias)186 void add_alias(mystring user, mystring alias)
187 {
188 alias = alias.lower();
189 user = user.lower();
190 if(!domain.exists(alias)) {
191 vpwentry vpw(alias, "*", domain.userdir(alias), user, false);
192 response resp = domain.set(&vpw, true);
193 if(!resp)
194 if(!o_quiet)
195 ferr << argv0base << ": warning: adding the alias '"
196 << alias
197 << "' failed:\n "
198 << resp.msg << endl;
199 else
200 if(!o_quiet)
201 fout << argv0base << ": alias '" << alias << "' successfully added"
202 << endl;
203 }
204 else
205 if(!o_quiet)
206 ferr << argv0base << ": warning: alias '" << alias << "' already exists."
207 << endl;
208 }
209
set_defaults()210 void set_defaults()
211 {
212 if(!strcmp(argv0base, "vaddalias"))
213 o_hasmailbox = false;
214 if(!o_hardquota)
215 o_hardquota = config->default_hardquota();
216 if(!o_softquota)
217 o_softquota = config->default_softquota();
218 if(!o_msgsize)
219 o_msgsize = config->default_msgsize();
220 if(!o_msgcount)
221 o_msgcount = config->default_msgcount();
222 if(!o_expiry)
223 o_expiry = config->default_expiry();
224 if(o_expiry != -1)
225 o_expiry += time(0);
226 }
227
cli_main(int argc,char * argv[])228 int cli_main(int argc, char* argv[])
229 {
230 if(!go_home())
231 return 1;
232
233 set_defaults();
234
235 add_user(argv[0]);
236 if(!o_quiet)
237 fout << argv0base << ": user '" << argv[0] << "' successfully added"
238 << endl;
239
240 for(int i = 1; i < argc; i++)
241 add_alias(argv[0], argv[i]);
242
243 return 0;
244 }
245