1 // Copyright (C) 2000 Mike Bell <mike@mikebell.org>,
2 // Bruce Guenter <bruceg@em.ca>
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18 #include <config.h>
19 #include <stdlib.h>
20 #include <sys/stat.h>
21 #include <stdio.h>
22 #include "daemon.h"
23 #include "config/configrc.h"
24 #include "misc/response.h"
25 #include "misc/lookup.h"
26 #include "misc/maildir.h"
27 #include "misc/pwentry_table.h"
28 #include "misc/stat_fns.h"
29
autoresponse_write(const mystring & directory,const mystring & location,const mystring & disabled,const mystring & msg)30 response autoresponse_write(const mystring& directory,
31 const mystring& location,
32 const mystring& disabled,
33 const mystring& msg)
34 {
35 mystring tmpfile = location + ".lock";
36
37 if(!is_dir(directory.c_str())) {
38 if(mkdir(directory.c_str(), 0755))
39 RETURN(err, "Could not create autoresponse directory");
40 }
41
42 if(is_exist(tmpfile.c_str()))
43 RETURN(err, "Temporary autoresponse file already exists");
44
45 if(is_exist(disabled.c_str()))
46 RETURN(err, "Autoresponse is disabled, reenable it before writing a new message");
47
48 fdobuf out(tmpfile.c_str(), fdobuf::create | fdobuf::excl, 0644);
49 if(!out)
50 RETURN(err, "Unable to open temporary autoresponse file for writing");
51
52 out << msg;
53 if(!out.flush() || !out.close()) {
54 unlink(tmpfile.c_str());
55 RETURN(err, "Unable to write message to file");
56 }
57 if(rename(tmpfile.c_str(), location.c_str())) {
58 unlink(tmpfile.c_str());
59 RETURN(err, "Unable to rename temporary autoresponse file");
60 }
61
62 RETURN(ok, "Message successfully written to autoresponse file");
63 }
64
autoresponse_disable(const mystring & location,const mystring & disabled)65 response autoresponse_disable(const mystring& location,
66 const mystring& disabled)
67 {
68 if(!is_exist(location.c_str()))
69 RETURN(ok, "Autoresponse file did not exist");
70 if(is_exist(disabled.c_str()))
71 RETURN(err, "Disabled autoresponse file already exists");
72 if(rename(location.c_str(), disabled.c_str()))
73 RETURN(err, "Unable to rename autoresponse file");
74 RETURN(ok, "Autoresponse file sucessfully disabled");
75 }
76
autoresponse_enable(const mystring & location,const mystring & disabled)77 response autoresponse_enable(const mystring& location,
78 const mystring& disabled)
79 {
80 if(is_exist(location.c_str()))
81 RETURN(ok, "Autoresponse is already enabled");
82 if(!is_exist(disabled.c_str()))
83 RETURN(err, "Disabled autoresponse file did not exist");
84 if(rename(disabled.c_str(), location.c_str()))
85 RETURN(err, "Unable to rename previously disabled autoresponse file");
86 RETURN(ok, "Autoresponse file sucessfully restored");
87 }
88
read_file(const mystring & filename,mystring & out)89 static bool read_file(const mystring& filename, mystring& out)
90 {
91 fdibuf in(filename.c_str());
92 if(!in)
93 return false;
94 char contents[65536];
95 unsigned contentlen;
96 in.read(contents, 65536);
97 contentlen = in.last_count();
98 out = mystring(contents, contentlen);
99 return true;
100 }
101
autoresponse_read(const mystring & location,const mystring & disabled,int fd)102 response autoresponse_read(const mystring& location,
103 const mystring& disabled, int fd)
104 {
105 mystring line;
106 if(!is_exist(location.c_str()) &&
107 !is_exist(disabled.c_str()))
108 RETURN(err, "Autoresponder file does not exist");
109
110 mystring contents;
111 if(!read_file(location, contents) &&
112 !read_file(disabled, contents))
113 RETURN(err, "Unable to read data from autoresponse file");
114 response resp(response::ok, contents);
115 resp.write(fd);
116 RETURN(ok, "Retrieved autoresponse file");
117 }
118
autoresponse_delete(const mystring & directory)119 response autoresponse_delete(const mystring& directory)
120 {
121 if(!is_dir(directory.c_str()))
122 RETURN(err, "Autoresponse directory does not exist.");
123 if(!delete_directory(directory))
124 RETURN(err, "Could not delete autoresponse directory.");
125 RETURN(ok, "Autoresponse directory deleted.");
126 }
127
autoresponse_status(const mystring & directory,const mystring & location,const mystring & disabled)128 response autoresponse_status(const mystring& directory,
129 const mystring& location,
130 const mystring& disabled)
131 {
132 const char* msg;
133 if(is_exist(location.c_str()))
134 msg = "enabled";
135 else if(is_exist(disabled.c_str()))
136 msg = "disabled";
137 else if(is_dir(directory.c_str()))
138 msg = "missing message file";
139 else
140 msg = "nonexistant";
141 RETURN(ok, msg);
142 }
143
CMD_FD(autoresponse)144 CMD_FD(autoresponse)
145 // Usage: autoresponse baseuser-virtuser pass action [autorespmessage]
146 {
147
148 mystring user = args[0];
149 mystring pass = args[1];
150 args[1] = LOG_PASSWORD;
151 mystring action = args[2];
152 mystring message;
153 if(args.count() == 4) {
154 message = args[3];
155 args[3] = LOG_MESSAGE;
156 }
157 logcommand(args);
158
159 pwentry* pw;
160 vpwentry* vpw;
161 OK_RESPONSE(lookup_and_validate(user, pw, vpw, pass, true, true));
162
163 const mystring directory = vpw->directory + "/" + config->autoresponse_dir();
164 const mystring filename = directory + "/" + config->autoresponse_file();
165 const mystring disabled = filename + ".disabled";
166
167 if(action == "disable")
168 return autoresponse_disable(filename, disabled);
169 else if(action == "enable")
170 return autoresponse_enable(filename, disabled);
171 else if(action == "read")
172 return autoresponse_read(filename, disabled, fd);
173 else if(action == "write")
174 if(!message)
175 RETURN(bad, "Missing autoresponse message argument");
176 else
177 return autoresponse_write(directory, filename, disabled, message);
178 else if(action == "delete")
179 return autoresponse_delete(directory);
180 else if(action == "status")
181 return autoresponse_status(directory, filename, disabled);
182
183 RETURN(err, "Unrecognized command");
184 }
185