portal: Use readLine and not getPass when stdin is not a terminal
[hcoop/domtool2.git] / src / msg.sml
CommitLineData
36e42cb8
AC
1(* HCoop Domtool (http://hcoop.sourceforge.net/)
2 * Copyright (c) 2006, Adam Chlipala
617696c6 3 * Copyright (c) 2011,2014 Clinton Ebadi <clinton@unknownlamer.org>
36e42cb8
AC
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 *)
19
20(* Network messages *)
21
22structure Msg :> MSG = struct
23
24open OpenSSL MsgTypes Slave
25
26val a2i = fn Add => 0
1638d5a2 27 | Delete true => 1
36e42cb8 28 | Modify => 2
1638d5a2 29 | Delete false => 3
36e42cb8
AC
30
31val i2a = fn 0 => Add
1638d5a2 32 | 1 => Delete true
36e42cb8 33 | 2 => Modify
1638d5a2 34 | 3 => Delete false
36e42cb8
AC
35 | _ => raise OpenSSL.OpenSSL "Bad action number to deserialize"
36
5ee41dd0
AC
37fun sendAcl (bio, {user, class, value}) =
38 (OpenSSL.writeString (bio, user);
39 OpenSSL.writeString (bio, class);
40 OpenSSL.writeString (bio, value))
41
42fun recvAcl bio =
43 case (OpenSSL.readString bio, OpenSSL.readString bio, OpenSSL.readString bio) of
44 (SOME user, SOME class, SOME value) => SOME {user = user, class = class, value = value}
45 | _ => NONE
46
c53e82e4
AC
47fun sendList f (bio, ls) =
48 (app (fn x =>
49 (OpenSSL.writeInt (bio, 1);
50 f (bio, x))) ls;
51 OpenSSL.writeInt (bio, 0))
52
53fun recvList f bio =
54 let
55 fun loop ls =
56 case OpenSSL.readInt bio of
57 SOME 0 => SOME (rev ls)
58 | SOME 1 =>
59 (case f bio of
60 SOME x => loop (x :: ls)
61 | NONE => NONE)
62 | _ => NONE
63 in
64 loop []
65 end
66
21d921a5
AC
67fun sendOption f (bio, opt) =
68 case opt of
69 NONE => OpenSSL.writeInt (bio, 0)
70 | SOME x => (OpenSSL.writeInt (bio, 1);
71 f (bio, x))
72
73fun recvOption f bio =
74 case OpenSSL.readInt bio of
75 SOME 0 => SOME NONE
76 | SOME 1 =>
77 (case f bio of
78 SOME x => SOME (SOME x)
79 | NONE => NONE)
80 | _ => NONE
81
2e96b9d4
AC
82fun sendBool (bio, b) =
83 if b then
84 OpenSSL.writeInt (bio, 1)
85 else
86 OpenSSL.writeInt (bio, 0)
87
88fun recvBool bio =
89 case OpenSSL.readInt bio of
90 SOME 0 => SOME false
91 | SOME 1 => SOME true
92 | _ => NONE
93
737c68d4
AC
94fun sendSockPerm (bio, p) =
95 case p of
96 Any => OpenSSL.writeInt (bio, 0)
97 | Client => OpenSSL.writeInt (bio, 1)
98 | Server => OpenSSL.writeInt (bio, 2)
99 | Nada => OpenSSL.writeInt (bio, 3)
100
101fun recvSockPerm bio =
102 case OpenSSL.readInt bio of
103 SOME 0 => SOME Any
104 | SOME 1 => SOME Client
105 | SOME 2 => SOME Server
106 | SOME 3 => SOME Nada
107 | _ => NONE
108
a95a0107
AC
109fun sendQuery (bio, q) =
110 case q of
111 QApt s => (OpenSSL.writeInt (bio, 0);
112 OpenSSL.writeString (bio, s))
d351d679
AC
113 | QCron s => (OpenSSL.writeInt (bio, 1);
114 OpenSSL.writeString (bio, s))
115 | QFtp s => (OpenSSL.writeInt (bio, 2);
116 OpenSSL.writeString (bio, s))
4d5126e1
AC
117 | QTrustedPath s => (OpenSSL.writeInt (bio, 3);
118 OpenSSL.writeString (bio, s))
737c68d4
AC
119 | QSocket s => (OpenSSL.writeInt (bio, 4);
120 OpenSSL.writeString (bio, s))
167cffff
CE
121 | QFirewall {node, user} => (OpenSSL.writeInt (bio, 5);
122 OpenSSL.writeString (bio, node);
123 OpenSSL.writeString (bio, user))
991d8e66
CE
124 | QAptExists s => (OpenSSL.writeInt (bio, 6);
125 OpenSSL.writeString (bio, s))
a95a0107
AC
126
127fun recvQuery bio =
128 case OpenSSL.readInt bio of
129 SOME n =>
130 (case n of
131 0 => Option.map QApt (OpenSSL.readString bio)
d351d679
AC
132 | 1 => Option.map QCron (OpenSSL.readString bio)
133 | 2 => Option.map QFtp (OpenSSL.readString bio)
4d5126e1 134 | 3 => Option.map QTrustedPath (OpenSSL.readString bio)
737c68d4 135 | 4 => Option.map QSocket (OpenSSL.readString bio)
167cffff
CE
136 | 5 => (case ((OpenSSL.readString bio), (OpenSSL.readString bio)) of
137 (SOME node, SOME user) => SOME (QFirewall { node = node, user = user })
138 | _ => NONE)
991d8e66 139 | 6 => Option.map QAptExists (OpenSSL.readString bio)
a95a0107
AC
140 | _ => NONE)
141 | NONE => NONE
142
36e42cb8
AC
143fun send (bio, m) =
144 case m of
145 MsgOk => OpenSSL.writeInt (bio, 1)
146 | MsgError s => (OpenSSL.writeInt (bio, 2);
147 OpenSSL.writeString (bio, s))
148 | MsgConfig s => (OpenSSL.writeInt (bio, 3);
149 OpenSSL.writeString (bio, s))
150 | MsgFile {action, domain, dir, file} =>
151 (OpenSSL.writeInt (bio, 4);
152 OpenSSL.writeInt (bio, a2i action);
153 OpenSSL.writeString (bio, domain);
154 OpenSSL.writeString (bio, dir);
155 OpenSSL.writeString (bio, file))
156 | MsgDoFiles => OpenSSL.writeInt (bio, 5)
5ee41dd0
AC
157 | MsgGrant acl => (OpenSSL.writeInt (bio, 6);
158 sendAcl (bio, acl))
411a85f2
AC
159 | MsgRevoke acl => (OpenSSL.writeInt (bio, 7);
160 sendAcl (bio, acl))
08a04eb4
AC
161 | MsgListPerms user => (OpenSSL.writeInt (bio, 8);
162 OpenSSL.writeString (bio, user))
163 | MsgPerms classes => (OpenSSL.writeInt (bio, 9);
c53e82e4
AC
164 sendList (fn (bio, (class, values)) =>
165 (OpenSSL.writeString (bio, class);
166 sendList OpenSSL.writeString (bio, values)))
167 (bio, classes))
094877b1
AC
168 | MsgWhoHas {class, value} => (OpenSSL.writeInt (bio, 10);
169 OpenSSL.writeString (bio, class);
170 OpenSSL.writeString (bio, value))
171 | MsgWhoHasResponse users => (OpenSSL.writeInt (bio, 11);
c53e82e4
AC
172 sendList OpenSSL.writeString (bio, users))
173 | MsgMultiConfig codes => (OpenSSL.writeInt (bio, 12);
174 sendList OpenSSL.writeString (bio, codes))
e69e60cc
AC
175 | MsgRmdom doms => (OpenSSL.writeInt (bio, 13);
176 sendList OpenSSL.writeString (bio, doms))
1824f573 177 | MsgRegenerate => OpenSSL.writeInt (bio, 14)
e69e60cc
AC
178 | MsgRmuser dom => (OpenSSL.writeInt (bio, 15);
179 OpenSSL.writeString (bio, dom))
21d921a5
AC
180 | MsgCreateDbUser {dbtype, passwd} => (OpenSSL.writeInt (bio, 16);
181 OpenSSL.writeString (bio, dbtype);
182 sendOption OpenSSL.writeString (bio, passwd))
fe789bea
AC
183 | MsgCreateDb {dbtype, dbname, encoding} => (OpenSSL.writeInt (bio, 17);
184 OpenSSL.writeString (bio, dbtype);
185 OpenSSL.writeString (bio, dbname);
186 sendOption OpenSSL.writeString (bio, encoding))
08688401
AC
187 | MsgNewMailbox {domain, user, passwd, mailbox} =>
188 (OpenSSL.writeInt (bio, 18);
189 OpenSSL.writeString (bio, domain);
190 OpenSSL.writeString (bio, user);
191 OpenSSL.writeString (bio, passwd);
192 OpenSSL.writeString (bio, mailbox))
193 | MsgPasswdMailbox {domain, user, passwd} =>
194 (OpenSSL.writeInt (bio, 19);
195 OpenSSL.writeString (bio, domain);
196 OpenSSL.writeString (bio, user);
197 OpenSSL.writeString (bio, passwd))
198 | MsgRmMailbox {domain, user} =>
199 (OpenSSL.writeInt (bio, 20);
200 OpenSSL.writeString (bio, domain);
201 OpenSSL.writeString (bio, user))
1d3ef80e
AC
202 | MsgListMailboxes domain =>
203 (OpenSSL.writeInt (bio, 21);
204 OpenSSL.writeString (bio, domain))
205 | MsgMailboxes users =>
206 (OpenSSL.writeInt (bio, 22);
2fc6b0dd
AC
207 sendList (fn (bio, {user, mailbox}) =>
208 (OpenSSL.writeString (bio, user);
209 OpenSSL.writeString (bio, mailbox)))
210 (bio, users))
2e96b9d4
AC
211 | MsgSaQuery addr => (OpenSSL.writeInt (bio, 23);
212 OpenSSL.writeString (bio, addr))
213 | MsgSaStatus b => (OpenSSL.writeInt (bio, 24);
214 sendBool (bio, b))
215 | MsgSaSet (addr, b) => (OpenSSL.writeInt (bio, 25);
216 OpenSSL.writeString (bio, addr);
217 sendBool (bio, b))
2bc5ed22
AC
218 | MsgSmtpLogReq domain => (OpenSSL.writeInt (bio, 26);
219 OpenSSL.writeString (bio, domain))
220 | MsgSmtpLogRes domain => (OpenSSL.writeInt (bio, 27);
221 OpenSSL.writeString (bio, domain))
86aa5de7
AC
222 | MsgDbPasswd {dbtype, passwd} => (OpenSSL.writeInt (bio, 28);
223 OpenSSL.writeString (bio, dbtype);
224 OpenSSL.writeString (bio, passwd))
9f27d58f 225 | MsgShutdown => OpenSSL.writeInt (bio, 29)
75585a67
AC
226 | MsgYes => OpenSSL.writeInt (bio, 30)
227 | MsgNo => OpenSSL.writeInt (bio, 31)
a95a0107
AC
228 | MsgQuery q => (OpenSSL.writeInt (bio, 32);
229 sendQuery (bio, q))
737c68d4
AC
230 | MsgSocket p => (OpenSSL.writeInt (bio, 33);
231 sendSockPerm (bio, p))
f9548f16
AC
232 | MsgFirewall ls => (OpenSSL.writeInt (bio, 34);
233 sendList OpenSSL.writeString (bio, ls))
fb6fac97 234 | MsgRegenerateTc => OpenSSL.writeInt (bio, 35)
35659203
AC
235 | MsgDropDb {dbtype, dbname} => (OpenSSL.writeInt (bio, 36);
236 OpenSSL.writeString (bio, dbtype);
237 OpenSSL.writeString (bio, dbname))
99cc4144
AC
238 | MsgGrantDb {dbtype, dbname} => (OpenSSL.writeInt (bio, 37);
239 OpenSSL.writeString (bio, dbtype);
240 OpenSSL.writeString (bio, dbname))
314ce7bd 241 | MsgMysqlFixperms => OpenSSL.writeInt (bio, 38)
1ffc47a6
AC
242 | MsgDescribe dom => (OpenSSL.writeInt (bio, 39);
243 OpenSSL.writeString (bio, dom))
244 | MsgDescription s => (OpenSSL.writeInt (bio, 40);
245 OpenSSL.writeString (bio, s))
563e7792 246 | MsgReUsers => OpenSSL.writeInt (bio, 41)
9b8c6dc8 247 | MsgVmailChanged => OpenSSL.writeInt (bio, 42)
73b95423 248 | MsgFirewallRegen => OpenSSL.writeInt (bio, 43)
f296c496
CE
249 | MsgAptQuery {section, description} => (OpenSSL.writeInt (bio, 44);
250 OpenSSL.writeString (bio, section);
251 OpenSSL.writeString (bio, description))
ebb51f80 252 | MsgSaChanged => OpenSSL.writeInt (bio, 45)
0e0442b0
CE
253 | MsgPortalPasswdMailbox {domain : string, user : string, oldpasswd : string, newpasswd : string} =>
254 (OpenSSL.writeInt (bio, 46);
255 OpenSSL.writeString (bio, domain);
256 OpenSSL.writeString (bio, user);
257 OpenSSL.writeString (bio, oldpasswd);
258 OpenSSL.writeString (bio, newpasswd))
36e42cb8
AC
259
260fun checkIt v =
261 case v of
262 NONE => raise OpenSSL.OpenSSL "Bad Msg format"
263 | _ => v
264
265fun recv bio =
266 case OpenSSL.readInt bio of
267 NONE => NONE
268 | SOME n =>
269 checkIt (case n of
270 1 => SOME MsgOk
271 | 2 => Option.map MsgError (OpenSSL.readString bio)
272 | 3 => Option.map MsgConfig (OpenSSL.readString bio)
273 | 4 => (case (OpenSSL.readInt bio,
274 OpenSSL.readString bio,
275 OpenSSL.readString bio,
276 OpenSSL.readString bio) of
277 (SOME action, SOME domain, SOME dir, SOME file) =>
278 SOME (MsgFile {action = i2a action,
279 domain = domain,
280 dir = dir,
281 file = file})
282 | _ => NONE)
283 | 5 => SOME MsgDoFiles
5ee41dd0
AC
284 | 6 => (case recvAcl bio of
285 SOME acl => SOME (MsgGrant acl)
286 | _ => NONE)
411a85f2
AC
287 | 7 => (case recvAcl bio of
288 SOME acl => SOME (MsgRevoke acl)
289 | _ => NONE)
08a04eb4
AC
290 | 8 => (case OpenSSL.readString bio of
291 SOME user => SOME (MsgListPerms user)
292 | _ => NONE)
c53e82e4
AC
293 | 9 => Option.map MsgPerms
294 (recvList (fn bio =>
295 case (OpenSSL.readString bio,
296 recvList OpenSSL.readString bio) of
297 (SOME class, SOME values) => SOME (class, values)
298 | _ => NONE) bio)
094877b1
AC
299 | 10 => (case (OpenSSL.readString bio, OpenSSL.readString bio) of
300 (SOME class, SOME value) => SOME (MsgWhoHas {class = class, value = value})
301 | _ => NONE)
c53e82e4
AC
302 | 11 => Option.map MsgWhoHasResponse
303 (recvList OpenSSL.readString bio)
304 | 12 => Option.map MsgMultiConfig
305 (recvList OpenSSL.readString bio)
e69e60cc 306 | 13 => Option.map MsgRmdom (recvList OpenSSL.readString bio)
1824f573 307 | 14 => SOME MsgRegenerate
e69e60cc 308 | 15 => Option.map MsgRmuser (OpenSSL.readString bio)
21d921a5
AC
309 | 16 => (case (OpenSSL.readString bio, recvOption OpenSSL.readString bio) of
310 (SOME dbtype, SOME passwd) =>
311 SOME (MsgCreateDbUser {dbtype = dbtype, passwd = passwd})
312 | _ => NONE)
fe789bea
AC
313 | 17 => (case (OpenSSL.readString bio, OpenSSL.readString bio, recvOption OpenSSL.readString bio) of
314 (SOME dbtype, SOME dbname, SOME encoding) =>
315 SOME (MsgCreateDb {dbtype = dbtype, dbname = dbname, encoding = encoding})
90dd48df 316 | _ => NONE)
08688401
AC
317 | 18 => (case (OpenSSL.readString bio, OpenSSL.readString bio,
318 OpenSSL.readString bio, OpenSSL.readString bio) of
319 (SOME domain, SOME user, SOME passwd, SOME mailbox) =>
320 SOME (MsgNewMailbox {domain = domain, user = user,
321 passwd = passwd, mailbox = mailbox})
322 | _ => NONE)
323 | 19 => (case (OpenSSL.readString bio, OpenSSL.readString bio,
324 OpenSSL.readString bio) of
325 (SOME domain, SOME user, SOME passwd) =>
326 SOME (MsgPasswdMailbox {domain = domain, user = user,
327 passwd = passwd})
328 | _ => NONE)
329 | 20 => (case (OpenSSL.readString bio, OpenSSL.readString bio) of
330 (SOME domain, SOME user) =>
331 SOME (MsgRmMailbox {domain = domain, user = user})
332 | _ => NONE)
1d3ef80e 333 | 21 => Option.map MsgListMailboxes (OpenSSL.readString bio)
2fc6b0dd
AC
334 | 22 => Option.map MsgMailboxes (recvList
335 (fn bio =>
336 case (OpenSSL.readString bio,
337 OpenSSL.readString bio) of
338 (SOME user, SOME mailbox) =>
339 SOME {user = user, mailbox = mailbox}
340 | _ => NONE)
341 bio)
2e96b9d4
AC
342 | 23 => Option.map MsgSaQuery (OpenSSL.readString bio)
343 | 24 => Option.map MsgSaStatus (recvBool bio)
344 | 25 => (case (OpenSSL.readString bio, recvBool bio) of
345 (SOME user, SOME b) => SOME (MsgSaSet (user, b))
346 | _ => NONE)
2bc5ed22
AC
347 | 26 => Option.map MsgSmtpLogReq (OpenSSL.readString bio)
348 | 27 => Option.map MsgSmtpLogRes (OpenSSL.readString bio)
86aa5de7
AC
349 | 28 => (case (OpenSSL.readString bio, OpenSSL.readString bio) of
350 (SOME dbtype, SOME passwd) =>
351 SOME (MsgDbPasswd {dbtype = dbtype, passwd = passwd})
352 | _ => NONE)
9f27d58f 353 | 29 => SOME MsgShutdown
75585a67
AC
354 | 30 => SOME MsgYes
355 | 31 => SOME MsgNo
a95a0107 356 | 32 => Option.map MsgQuery (recvQuery bio)
737c68d4 357 | 33 => Option.map MsgSocket (recvSockPerm bio)
f9548f16 358 | 34 => Option.map MsgFirewall (recvList OpenSSL.readString bio)
fb6fac97 359 | 35 => SOME MsgRegenerateTc
35659203
AC
360 | 36 => (case (OpenSSL.readString bio, OpenSSL.readString bio) of
361 (SOME dbtype, SOME dbname) =>
362 SOME (MsgDropDb {dbtype = dbtype, dbname = dbname})
363 | _ => NONE)
99cc4144
AC
364 | 37 => (case (OpenSSL.readString bio, OpenSSL.readString bio) of
365 (SOME dbtype, SOME dbname) =>
366 SOME (MsgGrantDb {dbtype = dbtype, dbname = dbname})
367 | _ => NONE)
00a077ab 368 | 38 => SOME MsgMysqlFixperms
1ffc47a6
AC
369 | 39 => Option.map MsgDescribe (OpenSSL.readString bio)
370 | 40 => Option.map MsgDescription (OpenSSL.readString bio)
563e7792 371 | 41 => SOME MsgReUsers
9b8c6dc8 372 | 42 => SOME MsgVmailChanged
73b95423 373 | 43 => SOME MsgFirewallRegen
f296c496
CE
374 | 44 => (case (OpenSSL.readString bio, OpenSSL.readString bio) of
375 (SOME section, SOME description) => SOME (MsgAptQuery {section = section, description = description})
376 | _ => NONE)
ebb51f80 377 | 45 => SOME MsgSaChanged
0e0442b0
CE
378 | 46 => (case (OpenSSL.readString bio, OpenSSL.readString bio, OpenSSL.readString bio, OpenSSL.readString bio) of
379 (SOME domain, SOME user, SOME oldpasswd, SOME newpasswd) =>
380 SOME (MsgPortalPasswdMailbox {domain = domain, user = user, oldpasswd = oldpasswd, newpasswd = newpasswd})
381 | _ => NONE)
36e42cb8
AC
382 | _ => NONE)
383
384end