1 /*
2 * Copyright conserver.com, 2000
3 *
4 * Maintainer/Enhancer: Bryan Stansell (bryan@conserver.com)
5 *
6 * Copyright GNAC, Inc., 1998
7 */
8
9 /*
10 * Copyright (c) 1990 The Ohio State University.
11 * All rights reserved.
12 *
13 * Redistribution and use in source and binary forms are permitted
14 * provided that: (1) source distributions retain this entire copyright
15 * notice and comment, and (2) distributions including binaries display
16 * the following acknowledgement: ``This product includes software
17 * developed by The Ohio State University and its contributors''
18 * in the documentation or other materials provided with the distribution
19 * and in all advertising materials mentioning features or use of this
20 * software. Neither the name of the University nor the names of its
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
26 */
27
28 #include <compat.h>
29
30 #include <pwd.h>
31
32 #include <cutil.h>
33 #include <consent.h>
34 #include <client.h>
35 #include <group.h>
36 #include <access.h>
37 #include <master.h>
38 #include <readcfg.h>
39 #include <version.h>
40
41 #include <dirent.h>
42 #if HAVE_OPENSSL
43 # include <openssl/opensslv.h>
44 #endif
45 #if HAVE_GSSAPI
46 # include <gssapi/gssapi.h>
47 #endif
48
49
50 int fAll = 0, fNoinit = 0, fVersion = 0, fStrip = 0, fReopen =
51 0, fNoautoreup = 0, fSyntaxOnly = 0;
52
53 char *pcConfig = CONFIGFILE;
54 int cMaxMemb = MAXMEMB;
55 #if USE_IPV6
56 struct addrinfo *bindAddr;
57 struct addrinfo *bindBaseAddr;
58 #else
59 in_addr_t bindAddr = INADDR_ANY;
60 unsigned short bindPort;
61 unsigned short bindBasePort;
62 struct sockaddr_in in_port;
63 #endif
64 static STRING *startedMsg = (STRING *)0;
65 CONFIG *optConf = (CONFIG *)0;
66 CONFIG *config = (CONFIG *)0;
67 char *interface = (char *)0;
68 CONFIG defConfig =
69 { (STRING *)0, FLAGTRUE, 'r', FLAGFALSE, LOGFILEPATH, PASSWDFILE,
70 DEFPORT,
71 FLAGTRUE, FLAGTRUE, 0, DEFBASEPORT, (char *)0, 0
72 #if HAVE_SETPROCTITLE
73 , FLAGFALSE
74 #endif
75 #if HAVE_OPENSSL
76 , (char *)0, FLAGTRUE, FLAGFALSE, (char *)0
77 #endif
78 };
79
80 CONSFILE *unifiedlog = (CONSFILE *)0;
81
82 #if HAVE_DMALLOC && DMALLOC_MARK_MAIN
83 unsigned long dmallocMarkMain = 0;
84 #endif
85
86 #if HAVE_OPENSSL
87 # if OPENSSL_VERSION_NUMBER < 0x10100000L
88 int
DH_set0_pqg(DH * dh,BIGNUM * p,BIGNUM * q,BIGNUM * g)89 DH_set0_pqg(DH *dh, BIGNUM * p, BIGNUM * q, BIGNUM * g)
90 {
91 /* If the fields p and g in d are NULL, the corresponding input
92 * parameters MUST be non-NULL. q may remain NULL.
93 */
94 if ((dh->p == NULL && p == NULL)
95 || (dh->g == NULL && g == NULL))
96 return 0;
97
98 if (p != NULL) {
99 BN_free(dh->p);
100 dh->p = p;
101 }
102 if (q != NULL) {
103 BN_free(dh->q);
104 dh->q = q;
105 }
106 if (g != NULL) {
107 BN_free(dh->g);
108 dh->g = g;
109 }
110
111 if (q != NULL) {
112 dh->length = BN_num_bits(q);
113 }
114
115 return 1;
116 }
117 # endif/* OPENSSL_VERSION_NUMBER < 0x10100000L */
118
119 SSL_CTX *ctx = (SSL_CTX *)0;
120 DH *dh512 = (DH *)0;
121 DH *dh1024 = (DH *)0;
122 DH *dh2048 = (DH *)0;
123 DH *dh4096 = (DH *)0;
124
125 DH *
DHFromArray(unsigned char * dh_p,size_t dh_p_size,unsigned char * dh_g,size_t dh_g_size)126 DHFromArray(unsigned char *dh_p, size_t dh_p_size, unsigned char *dh_g,
127 size_t dh_g_size)
128 {
129 DH *dh;
130 BIGNUM *p, *g;
131
132 p = BN_bin2bn(dh_p, dh_p_size, NULL);
133 if (p == NULL) {
134 return (NULL);
135 }
136
137 g = BN_bin2bn(dh_g, dh_g_size, NULL);
138 if (g == NULL) {
139 BN_free(g);
140 return (NULL);
141 }
142
143 if ((dh = DH_new()) == NULL) {
144 BN_free(p);
145 BN_free(g);
146 return (NULL);
147 }
148
149 if (!DH_set0_pqg(dh, p, NULL, g)) {
150 BN_free(p);
151 BN_free(g);
152 DH_free(dh);
153 return (NULL);
154 }
155
156 return (dh);
157 }
158
159 DH *
GetDH512(void)160 GetDH512(void)
161 {
162 static unsigned char dh512_p[] = {
163 0xF5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40, 0x18, 0x11, 0x8D,
164 0x7C, 0x84, 0xA7, 0x0A, 0x72, 0xD6, 0x86, 0xC4, 0x03, 0x19,
165 0xC8, 0x07, 0x29, 0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F,
166 0xAB, 0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08, 0x3D,
167 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C, 0xBD, 0x89, 0x4B,
168 0x22, 0x19, 0x26, 0xBA, 0xAB, 0xA2, 0x5E, 0xC3, 0x55, 0xE9,
169 0x2A, 0x05, 0x5F,
170 };
171 static unsigned char dh512_g[] = {
172 0x02,
173 };
174
175 return DHFromArray(dh512_p, sizeof(dh512_p), dh512_g, sizeof(dh512_g));
176 }
177
178 DH *
GetDH1024(void)179 GetDH1024(void)
180 {
181 static unsigned char dh1024_p[] = {
182 0xF4, 0x88, 0xFD, 0x58, 0x4E, 0x49, 0xDB, 0xCD, 0x20, 0xB4, 0x9D,
183 0xE4, 0x91, 0x07, 0x36, 0x6B, 0x33, 0x6C, 0x38, 0x0D, 0x45,
184 0x1D, 0x0F, 0x7C, 0x88, 0xB3, 0x1C, 0x7C, 0x5B, 0x2D, 0x8E,
185 0xF6, 0xF3, 0xC9, 0x23, 0xC0, 0x43, 0xF0, 0xA5, 0x5B, 0x18,
186 0x8D, 0x8E, 0xBB, 0x55, 0x8C, 0xB8, 0x5D, 0x38, 0xD3, 0x34,
187 0xFD, 0x7C, 0x17, 0x57, 0x43, 0xA3, 0x1D, 0x18, 0x6C, 0xDE,
188 0x33, 0x21, 0x2C, 0xB5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29,
189 0x40, 0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72, 0xD6,
190 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29, 0x7A, 0xCA, 0x95,
191 0x0C, 0xD9, 0x96, 0x9F, 0xAB, 0xD0, 0x0A, 0x50, 0x9B, 0x02,
192 0x46, 0xD3, 0x08, 0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C,
193 0x7C, 0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB, 0xA2,
194 0x5E, 0xC3, 0x55, 0xE9, 0x2F, 0x78, 0xC7,
195 };
196 static unsigned char dh1024_g[] = {
197 0x02,
198 };
199
200 return DHFromArray(dh1024_p, sizeof(dh1024_p), dh1024_g,
201 sizeof(dh1024_g));
202 }
203
204 DH *
GetDH2048(void)205 GetDH2048(void)
206 {
207 static unsigned char dh2048_p[] = {
208 0xF6, 0x42, 0x57, 0xB7, 0x08, 0x7F, 0x08, 0x17, 0x72, 0xA2, 0xBA,
209 0xD6, 0xA9, 0x42, 0xF3, 0x05, 0xE8, 0xF9, 0x53, 0x11, 0x39,
210 0x4F, 0xB6, 0xF1, 0x6E, 0xB9, 0x4B, 0x38, 0x20, 0xDA, 0x01,
211 0xA7, 0x56, 0xA3, 0x14, 0xE9, 0x8F, 0x40, 0x55, 0xF3, 0xD0,
212 0x07, 0xC6, 0xCB, 0x43, 0xA9, 0x94, 0xAD, 0xF7, 0x4C, 0x64,
213 0x86, 0x49, 0xF8, 0x0C, 0x83, 0xBD, 0x65, 0xE9, 0x17, 0xD4,
214 0xA1, 0xD3, 0x50, 0xF8, 0xF5, 0x59, 0x5F, 0xDC, 0x76, 0x52,
215 0x4F, 0x3D, 0x3D, 0x8D, 0xDB, 0xCE, 0x99, 0xE1, 0x57, 0x92,
216 0x59, 0xCD, 0xFD, 0xB8, 0xAE, 0x74, 0x4F, 0xC5, 0xFC, 0x76,
217 0xBC, 0x83, 0xC5, 0x47, 0x30, 0x61, 0xCE, 0x7C, 0xC9, 0x66,
218 0xFF, 0x15, 0xF9, 0xBB, 0xFD, 0x91, 0x5E, 0xC7, 0x01, 0xAA,
219 0xD3, 0x5B, 0x9E, 0x8D, 0xA0, 0xA5, 0x72, 0x3A, 0xD4, 0x1A,
220 0xF0, 0xBF, 0x46, 0x00, 0x58, 0x2B, 0xE5, 0xF4, 0x88, 0xFD,
221 0x58, 0x4E, 0x49, 0xDB, 0xCD, 0x20, 0xB4, 0x9D, 0xE4, 0x91,
222 0x07, 0x36, 0x6B, 0x33, 0x6C, 0x38, 0x0D, 0x45, 0x1D, 0x0F,
223 0x7C, 0x88, 0xB3, 0x1C, 0x7C, 0x5B, 0x2D, 0x8E, 0xF6, 0xF3,
224 0xC9, 0x23, 0xC0, 0x43, 0xF0, 0xA5, 0x5B, 0x18, 0x8D, 0x8E,
225 0xBB, 0x55, 0x8C, 0xB8, 0x5D, 0x38, 0xD3, 0x34, 0xFD, 0x7C,
226 0x17, 0x57, 0x43, 0xA3, 0x1D, 0x18, 0x6C, 0xDE, 0x33, 0x21,
227 0x2C, 0xB5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40, 0x18,
228 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72, 0xD6, 0x86, 0xC4,
229 0x03, 0x19, 0xC8, 0x07, 0x29, 0x7A, 0xCA, 0x95, 0x0C, 0xD9,
230 0x96, 0x9F, 0xAB, 0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3,
231 0x08, 0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C, 0xBD,
232 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB, 0xA2, 0x5E, 0xC3,
233 0x55, 0xE9, 0x32, 0x0B, 0x3B,
234 };
235 static unsigned char dh2048_g[] = {
236 0x02,
237 };
238
239 return DHFromArray(dh2048_p, sizeof(dh2048_p), dh2048_g,
240 sizeof(dh2048_g));
241 }
242
243 DH *
GetDH4096(void)244 GetDH4096(void)
245 {
246 static unsigned char dh4096_p[] = {
247 0xFA, 0x14, 0x72, 0x52, 0xC1, 0x4D, 0xE1, 0x5A, 0x49, 0xD4, 0xEF,
248 0x09, 0x2D, 0xC0, 0xA8, 0xFD, 0x55, 0xAB, 0xD7, 0xD9, 0x37,
249 0x04, 0x28, 0x09, 0xE2, 0xE9, 0x3E, 0x77, 0xE2, 0xA1, 0x7A,
250 0x18, 0xDD, 0x46, 0xA3, 0x43, 0x37, 0x23, 0x90, 0x97, 0xF3,
251 0x0E, 0xC9, 0x03, 0x50, 0x7D, 0x65, 0xCF, 0x78, 0x62, 0xA6,
252 0x3A, 0x62, 0x22, 0x83, 0xA1, 0x2F, 0xFE, 0x79, 0xBA, 0x35,
253 0xFF, 0x59, 0xD8, 0x1D, 0x61, 0xDD, 0x1E, 0x21, 0x13, 0x17,
254 0xFE, 0xCD, 0x38, 0x87, 0x9E, 0xF5, 0x4F, 0x79, 0x10, 0x61,
255 0x8D, 0xD4, 0x22, 0xF3, 0x5A, 0xED, 0x5D, 0xEA, 0x21, 0xE9,
256 0x33, 0x6B, 0x48, 0x12, 0x0A, 0x20, 0x77, 0xD4, 0x25, 0x60,
257 0x61, 0xDE, 0xF6, 0xB4, 0x4F, 0x1C, 0x63, 0x40, 0x8B, 0x3A,
258 0x21, 0x93, 0x8B, 0x79, 0x53, 0x51, 0x2C, 0xCA, 0xB3, 0x7B,
259 0x29, 0x56, 0xA8, 0xC7, 0xF8, 0xF4, 0x7B, 0x08, 0x5E, 0xA6,
260 0xDC, 0xA2, 0x45, 0x12, 0x56, 0xDD, 0x41, 0x92, 0xF2, 0xDD,
261 0x5B, 0x8F, 0x23, 0xF0, 0xF3, 0xEF, 0xE4, 0x3B, 0x0A, 0x44,
262 0xDD, 0xED, 0x96, 0x84, 0xF1, 0xA8, 0x32, 0x46, 0xA3, 0xDB,
263 0x4A, 0xBE, 0x3D, 0x45, 0xBA, 0x4E, 0xF8, 0x03, 0xE5, 0xDD,
264 0x6B, 0x59, 0x0D, 0x84, 0x1E, 0xCA, 0x16, 0x5A, 0x8C, 0xC8,
265 0xDF, 0x7C, 0x54, 0x44, 0xC4, 0x27, 0xA7, 0x3B, 0x2A, 0x97,
266 0xCE, 0xA3, 0x7D, 0x26, 0x9C, 0xAD, 0xF4, 0xC2, 0xAC, 0x37,
267 0x4B, 0xC3, 0xAD, 0x68, 0x84, 0x7F, 0x99, 0xA6, 0x17, 0xEF,
268 0x6B, 0x46, 0x3A, 0x7A, 0x36, 0x7A, 0x11, 0x43, 0x92, 0xAD,
269 0xE9, 0x9C, 0xFB, 0x44, 0x6C, 0x3D, 0x82, 0x49, 0xCC, 0x5C,
270 0x6A, 0x52, 0x42, 0xF8, 0x42, 0xFB, 0x44, 0xF9, 0x39, 0x73,
271 0xFB, 0x60, 0x79, 0x3B, 0xC2, 0x9E, 0x0B, 0xDC, 0xD4, 0xA6,
272 0x67, 0xF7, 0x66, 0x3F, 0xFC, 0x42, 0x3B, 0x1B, 0xDB, 0x4F,
273 0x66, 0xDC, 0xA5, 0x8F, 0x66, 0xF9, 0xEA, 0xC1, 0xED, 0x31,
274 0xFB, 0x48, 0xA1, 0x82, 0x7D, 0xF8, 0xE0, 0xCC, 0xB1, 0xC7,
275 0x03, 0xE4, 0xF8, 0xB3, 0xFE, 0xB7, 0xA3, 0x13, 0x73, 0xA6,
276 0x7B, 0xC1, 0x0E, 0x39, 0xC7, 0x94, 0x48, 0x26, 0x00, 0x85,
277 0x79, 0xFC, 0x6F, 0x7A, 0xAF, 0xC5, 0x52, 0x35, 0x75, 0xD7,
278 0x75, 0xA4, 0x40, 0xFA, 0x14, 0x74, 0x61, 0x16, 0xF2, 0xEB,
279 0x67, 0x11, 0x6F, 0x04, 0x43, 0x3D, 0x11, 0x14, 0x4C, 0xA7,
280 0x94, 0x2A, 0x39, 0xA1, 0xC9, 0x90, 0xCF, 0x83, 0xC6, 0xFF,
281 0x02, 0x8F, 0xA3, 0x2A, 0xAC, 0x26, 0xDF, 0x0B, 0x8B, 0xBE,
282 0x64, 0x4A, 0xF1, 0xA1, 0xDC, 0xEE, 0xBA, 0xC8, 0x03, 0x82,
283 0xF6, 0x62, 0x2C, 0x5D, 0xB6, 0xBB, 0x13, 0x19, 0x6E, 0x86,
284 0xC5, 0x5B, 0x2B, 0x5E, 0x3A, 0xF3, 0xB3, 0x28, 0x6B, 0x70,
285 0x71, 0x3A, 0x8E, 0xFF, 0x5C, 0x15, 0xE6, 0x02, 0xA4, 0xCE,
286 0xED, 0x59, 0x56, 0xCC, 0x15, 0x51, 0x07, 0x79, 0x1A, 0x0F,
287 0x25, 0x26, 0x27, 0x30, 0xA9, 0x15, 0xB2, 0xC8, 0xD4, 0x5C,
288 0xCC, 0x30, 0xE8, 0x1B, 0xD8, 0xD5, 0x0F, 0x19, 0xA8, 0x80,
289 0xA4, 0xC7, 0x01, 0xAA, 0x8B, 0xBA, 0x53, 0xBB, 0x47, 0xC2,
290 0x1F, 0x6B, 0x54, 0xB0, 0x17, 0x60, 0xED, 0x79, 0x21, 0x95,
291 0xB6, 0x05, 0x84, 0x37, 0xC8, 0x03, 0xA4, 0xDD, 0xD1, 0x06,
292 0x69, 0x8F, 0x4C, 0x39, 0xE0, 0xC8, 0x5D, 0x83, 0x1D, 0xBE,
293 0x6A, 0x9A, 0x99, 0xF3, 0x9F, 0x0B, 0x45, 0x29, 0xD4, 0xCB,
294 0x29, 0x66, 0xEE, 0x1E, 0x7E, 0x3D, 0xD7, 0x13, 0x4E, 0xDB,
295 0x90, 0x90, 0x58, 0xCB, 0x5E, 0x9B, 0xCD, 0x2E, 0x2B, 0x0F,
296 0xA9, 0x4E, 0x78, 0xAC, 0x05, 0x11, 0x7F, 0xE3, 0x9E, 0x27,
297 0xD4, 0x99, 0xE1, 0xB9, 0xBD, 0x78, 0xE1, 0x84, 0x41, 0xA0,
298 0xDF,
299 };
300 static unsigned char dh4096_g[] = {
301 0x02,
302 };
303
304 return DHFromArray(dh4096_p, sizeof(dh4096_p), dh4096_g,
305 sizeof(dh4096_g));
306 }
307
308 DH *
TmpDHCallback(SSL * ssl,int is_export,int keylength)309 TmpDHCallback(SSL *ssl, int is_export, int keylength)
310 {
311 CONDDEBUG((1, "TmpDHCallback(): asked for a DH key length %u",
312 keylength));
313 switch (keylength) {
314 case 512:
315 if (dh512 == (DH *)0)
316 dh512 = GetDH512();
317 return dh512;
318 case 1024:
319 if (dh1024 == (DH *)0)
320 dh1024 = GetDH1024();
321 return dh1024;
322 case 2048:
323 if (dh2048 == (DH *)0)
324 dh2048 = GetDH2048();
325 return dh2048;
326 default:
327 if (dh4096 == (DH *)0)
328 dh4096 = GetDH4096();
329 return dh4096;
330 }
331 }
332
333 void
SetupSSL(void)334 SetupSSL(void)
335 {
336 if (ctx == (SSL_CTX *)0) {
337 char *ciphers;
338 int verifymode;
339 # if OPENSSL_VERSION_NUMBER < 0x10100000L
340 SSL_load_error_strings();
341 if (!SSL_library_init()) {
342 Error("SetupSSL(): SSL_library_init() failed");
343 Bye(EX_SOFTWARE);
344 }
345 # endif/* OPENSSL_VERSION_NUMBER < 0x10100000L */
346 if ((ctx = SSL_CTX_new(TLS_method())) == (SSL_CTX *)0) {
347 Error("SetupSSL(): SSL_CTX_new() failed");
348 Bye(EX_SOFTWARE);
349 }
350 if (SSL_CTX_set_default_verify_paths(ctx) != 1) {
351 Error
352 ("SetupSSL(): could not load SSL default CA file and/or directory");
353 Bye(EX_SOFTWARE);
354 }
355 if (config->sslcredentials != (char *)0) {
356 if (SSL_CTX_use_certificate_chain_file
357 (ctx, config->sslcredentials) != 1) {
358 Error
359 ("SetupSSL(): could not load SSL certificate from `%s'",
360 config->sslcredentials);
361 Bye(EX_SOFTWARE);
362 }
363 if (SSL_CTX_use_PrivateKey_file
364 (ctx, config->sslcredentials, SSL_FILETYPE_PEM) != 1) {
365 Error
366 ("SetupSSL(): could not load SSL private key from `%s'",
367 config->sslcredentials);
368 Bye(EX_SOFTWARE);
369 }
370 ciphers = "ALL:!LOW:!EXP:!MD5:!aNULL:@STRENGTH";
371 } else {
372 ciphers = "ALL:aNULL:!LOW:!EXP:!MD5:@STRENGTH" CIPHER_SEC0;
373 }
374 if (config->sslcacertificatefile != (char *)0) {
375 STACK_OF(X509_NAME) * cert_names;
376
377 cert_names =
378 SSL_load_client_CA_file(config->sslcacertificatefile);
379 if (cert_names != NULL) {
380 SSL_CTX_set_client_CA_list(ctx, cert_names);
381 if (SSL_CTX_load_verify_locations
382 (ctx, config->sslcacertificatefile, NULL) != 1) {
383 Error("Could not setup CA certificate file to '%s'",
384 config->sslcacertificatefile);
385 Bye(EX_UNAVAILABLE);
386 }
387 } else {
388 Error
389 ("SetupSSL(): could not load SSL client CA list from `%s'",
390 config->sslcacertificatefile);
391 Bye(EX_SOFTWARE);
392 }
393 }
394
395 verifymode = SSL_VERIFY_PEER;
396 if (config->sslreqclientcert == FLAGTRUE)
397 verifymode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
398 SSL_CTX_set_verify(ctx, verifymode, SSLVerifyCallback);
399 SSL_CTX_set_options(ctx,
400 SSL_OP_ALL | SSL_OP_NO_SSLv2 |
401 SSL_OP_SINGLE_DH_USE);
402 SSL_CTX_set_mode(ctx,
403 SSL_MODE_ENABLE_PARTIAL_WRITE |
404 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
405 SSL_MODE_AUTO_RETRY);
406 SSL_CTX_set_tmp_dh_callback(ctx, TmpDHCallback);
407 if (SSL_CTX_set_cipher_list(ctx, ciphers) != 1) {
408 Error("SetupSSL(): setting SSL cipher list failed");
409 Bye(EX_SOFTWARE);
410 }
411 /* might want to turn this back on at some point, but i can't
412 * see why right now.
413 */
414 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
415 }
416 }
417 #endif
418
419 #if HAVE_GSSAPI
420 gss_name_t gss_myname = GSS_C_NO_NAME;
421 gss_cred_id_t gss_mycreds = GSS_C_NO_CREDENTIAL;
422
423 void
SetupGSSAPI(void)424 SetupGSSAPI(void)
425 {
426 OM_uint32 stmaj, stmin;
427 char namestr[128];
428 gss_buffer_desc namebuf;
429
430 snprintf(namestr, 128, "host@%s", myHostname);
431 namebuf.value = namestr;
432 namebuf.length = strlen(namestr) + 1;
433 stmaj =
434 gss_import_name(&stmin, &namebuf, GSS_C_NT_HOSTBASED_SERVICE,
435 &gss_myname);
436 /* XXX: handle error */
437 if (stmaj != GSS_S_COMPLETE) {
438 Error("gss_import_name failed");
439 }
440 /* Get some initial credentials */
441 stmaj =
442 gss_acquire_cred(&stmin, gss_myname, 0, GSS_C_NULL_OID_SET,
443 GSS_C_ACCEPT, &gss_mycreds, NULL, NULL);
444 if (stmaj != GSS_S_COMPLETE) {
445 Error("Could not acquire GSS-API credentials");
446 }
447
448 }
449 #endif
450
451 void
ReopenLogfile(void)452 ReopenLogfile(void)
453 {
454 static int tag = 1;
455 /* redirect stdout and stderr to the logfile.
456 *
457 * first time through any problems will show up (stderr still there).
458 * after that, all bets are off...probably not see the errors (well,
459 * aside from the tail of the old logfile, if it was rolled).
460 */
461 if (config->daemonmode != FLAGTRUE)
462 return;
463
464 close(1);
465
466 /* so, if we aren't in daemon mode, we just return before closing
467 * anything. if we are, there are two possibilities. first, if
468 * logfile is set, we close fd 1, open a file, etc. all should be
469 * well. if logfile isn't set, we end up closing fd 1 and 2 and
470 * returning (in case the logfile was set and then unset [config
471 * file change]).
472 */
473 if (config->logfile == (char *)0) {
474 close(2);
475 return;
476 }
477
478 if (1 != open(config->logfile, O_WRONLY | O_CREAT | O_APPEND, 0644)) {
479 tag = 0;
480 Error("ReopenLogfile(): open(%s): %s", config->logfile,
481 strerror(errno));
482 Bye(EX_TEMPFAIL);
483 }
484 close(2);
485 dup(1);
486 if (isMaster && tag) {
487 Msg(MyVersion());
488 Msg(startedMsg->string);
489 }
490 tag = 0;
491 }
492
493 void
ReopenUnifiedlog(void)494 ReopenUnifiedlog(void)
495 {
496 /* close any existing */
497 if (unifiedlog != (CONSFILE *)0)
498 FileClose(&unifiedlog);
499
500 /* return if we aren't opening again */
501 if (config->unifiedlog == (char *)0)
502 return;
503
504 /* open a new one */
505 if ((unifiedlog =
506 FileOpen(config->unifiedlog, O_WRONLY | O_CREAT | O_APPEND,
507 0644)) == (CONSFILE *)0) {
508 Error("ReopenUnifiedlog(): open(%s): %s", config->unifiedlog,
509 strerror(errno));
510 return;
511 }
512 }
513
514 /* become a daemon (ksb)
515 */
516 static void
Daemonize(void)517 Daemonize(void)
518 {
519 int res;
520 #if !HAVE_SETSID
521 int td;
522 #endif
523
524 Msg("daemonizing");
525 SimpleSignal(SIGQUIT, SIG_IGN);
526 SimpleSignal(SIGINT, SIG_IGN);
527 #if defined(SIGTTOU)
528 SimpleSignal(SIGTTOU, SIG_IGN);
529 #endif
530 #if defined(SIGTTIN)
531 SimpleSignal(SIGTTIN, SIG_IGN);
532 #endif
533 #if defined(SIGTSTP)
534 SimpleSignal(SIGTSTP, SIG_IGN);
535 #endif
536 #if defined(SIGXFSZ)
537 SimpleSignal(SIGXFSZ, SIG_IGN);
538 #endif
539
540 fflush(stdout);
541 fflush(stderr);
542
543 switch (res = fork()) {
544 case -1:
545 Error("Daemonize(): fork(): %s", strerror(errno));
546 Bye(EX_TEMPFAIL);
547 case 0:
548 thepid = getpid();
549 break;
550 default:
551 Bye(EX_OK);
552 }
553
554 ReopenLogfile();
555
556 /* Further disassociate this process from the terminal
557 * Maybe this will allow you to start a daemon from rsh,
558 * i.e. with no controlling terminal.
559 */
560 #if HAVE_SETSID
561 setsid();
562 #else
563 tcsetpgrp(0, getpid());
564
565 /* lose our controlling terminal
566 */
567 if (-1 != (td = open("/dev/tty", O_RDWR, 0600))) {
568 ioctl(td, TIOCNOTTY, (char *)0);
569 close(td);
570 }
571 #endif
572 }
573
574
575 /* output a long message to the user (ksb)
576 */
577 static void
Usage(int wantfull)578 Usage(int wantfull)
579 {
580 static char u_terse[] =
581 "[-7dDEFhinoRSuvV] [-a type] [-m max] [-M master] [-p port] [-b port] [-c cred] [-C config] [-P passwd] [-L logfile] [-O min] [-U logfile]";
582 static char *full[] = {
583 "7 strip the high bit off all console data",
584 "a type set the default access type",
585 "b port base port for secondary channel (any by default)",
586 #if HAVE_OPENSSL
587 "c cred load an SSL certificate and key from the PEM encoded file",
588 #else
589 "c cred ignored - encryption not compiled into code",
590 #endif
591 "C config give a new config file to the server process",
592 "d become a daemon, redirecting stdout/stderr to logfile",
593 "D enable debug output, sent to stderr",
594 #if HAVE_OPENSSL
595 "E don't require encrypted client connections",
596 #else
597 "E ignored - encryption not compiled into code",
598 #endif
599 "F do not automatically reinitialize failed consoles",
600 "h output this message",
601 "i initialize console connections on demand",
602 "L logfile give a new logfile path to the server process",
603 "m max maximum consoles managed per process",
604 #if USE_UNIX_DOMAIN_SOCKETS
605 "M master directory that holds the Unix domain sockets",
606 #else
607 "M master address to listen on (all addresses by default)",
608 #endif
609 "n obsolete - see -u",
610 "o reopen downed console on client connect",
611 "O min reopen all downed consoles every <min> minutes",
612 #if USE_UNIX_DOMAIN_SOCKETS
613 "p port ignored - Unix domain sockets compiled into code",
614 #else
615 "p port port to listen on",
616 #endif
617 "P passwd give a new passwd file to the server process",
618 "R disable automatic client redirection",
619 "S syntax check of configuration file",
620 "u copy \"unloved\" console data to stdout",
621 "U logfile copy all console data to the \"unified\" logfile",
622 "v be verbose on startup",
623 "V output version info",
624 (char *)0
625 };
626 fprintf(stderr, "usage: %s %s\n", progname, u_terse);
627 if (wantfull) {
628 int i;
629 for (i = 0; full[i] != (char *)0; i++)
630 fprintf(stderr, "\t%s\n", full[i]);
631 }
632 }
633
634 /* show the user our version info (ksb)
635 */
636 static void
Version(void)637 Version(void)
638 {
639 static STRING *acA1 = (STRING *)0;
640 static STRING *acA2 = (STRING *)0;
641 int i;
642 char *optionlist[] = {
643 #if HAVE_DMALLOC
644 "dmalloc",
645 #endif
646 #if HAVE_FREEIPMI
647 "freeipmi",
648 #endif
649 #if USE_LIBWRAP
650 "libwrap",
651 #endif
652 #if HAVE_OPENSSL
653 "openssl",
654 #endif
655 #if HAVE_PAM
656 "pam",
657 #endif
658 #if TRUST_REVERSE_DNS
659 "trustrevdns",
660 #endif
661 #if USE_UNIX_DOMAIN_SOCKETS
662 "uds",
663 #endif
664 (char *)0
665 };
666
667 if (acA1 == (STRING *)0)
668 acA1 = AllocString();
669 if (acA2 == (STRING *)0)
670 acA2 = AllocString();
671
672 isMultiProc = 0;
673
674 Msg(MyVersion());
675 Msg("default access type `%c'", defConfig.defaultaccess);
676 Msg("default escape sequence `%s%s'", FmtCtl(DEFATTN, acA1),
677 FmtCtl(DEFESC, acA2));
678 Msg("default configuration in `%s'", CONFIGFILE);
679 Msg("default password in `%s'", defConfig.passwdfile);
680 Msg("default logfile is `%s'", defConfig.logfile);
681 Msg("default pidfile is `%s'", PIDFILE);
682 Msg("default limit is %d member%s per group", MAXMEMB,
683 MAXMEMB == 1 ? "" : "s");
684 #if USE_UNIX_DOMAIN_SOCKETS
685 Msg("default socket directory `%s'", UDSDIR);
686 #else
687 Msg("default primary port referenced as `%s'", defConfig.primaryport);
688 Msg("default secondary base port referenced as `%s'",
689 defConfig.secondaryport);
690 #endif
691
692 BuildString((char *)0, acA1);
693 if (optionlist[0] == (char *)0)
694 BuildString("none", acA1);
695 for (i = 0; optionlist[i] != (char *)0; i++) {
696 if (i == 0)
697 BuildString(optionlist[i], acA1);
698 else {
699 BuildString(", ", acA1);
700 BuildString(optionlist[i], acA1);
701 }
702 }
703 Msg("options: %s", acA1->string);
704 #if HAVE_DMALLOC
705 BuildString((char *)0, acA1);
706 BuildStringChar('0' + DMALLOC_VERSION_MAJOR, acA1);
707 BuildStringChar('.', acA1);
708 BuildStringChar('0' + DMALLOC_VERSION_MINOR, acA1);
709 BuildStringChar('.', acA1);
710 BuildStringChar('0' + DMALLOC_VERSION_PATCH, acA1);
711 # if defined(DMALLOC_VERSION_BETA)
712 if (DMALLOC_VERSION_BETA != 0) {
713 BuildString("-b", acA1);
714 BuildStringChar('0' + DMALLOC_VERSION_BETA, acA1);
715 }
716 # endif
717 Msg("dmalloc version: %s", acA1->string);
718 #endif
719 #if HAVE_FREEIPMI
720 BuildString((char *)0, acA1);
721 BuildStringChar('0' + LIBIPMICONSOLE_VERSION_MAJOR, acA1);
722 BuildStringChar('.', acA1);
723 BuildStringChar('0' + LIBIPMICONSOLE_VERSION_MINOR, acA1);
724 BuildStringChar('.', acA1);
725 BuildStringChar('0' + LIBIPMICONSOLE_VERSION_PATCH, acA1);
726 Msg("freeipmi version: %s", acA1->string);
727 #endif
728 #if HAVE_OPENSSL
729 Msg("openssl version: %s", OPENSSL_VERSION_TEXT);
730 #endif
731 Msg("built with `%s'", CONFIGINVOCATION);
732
733 if (fVerbose)
734 printf(COPYRIGHT);
735 Bye(EX_OK);
736 }
737
738 void
DestroyDataStructures(void)739 DestroyDataStructures(void)
740 {
741 GRPENT *pGE;
742 REMOTE *pRC;
743 ACCESS *pAC;
744
745 while (pGroups != (GRPENT *)0) {
746 pGE = pGroups->pGEnext;
747 DestroyGroup(pGroups);
748 pGroups = pGE;
749 }
750
751 while (pRCList != (REMOTE *)0) {
752 pRC = pRCList->pRCnext;
753 DestroyRemoteConsole(pRCList);
754 pRCList = pRC;
755 }
756
757 while (pACList != (ACCESS *)0) {
758 pAC = pACList->pACnext;
759 DestroyAccessList(pACList);
760 pACList = pAC;
761 }
762 DestroyConsentUsers(&pADList);
763 DestroyConsentUsers(&pLUList);
764
765 DestroyConfig(pConfig);
766 DestroyConfig(optConf);
767 DestroyConfig(config);
768
769 #if HAVE_OPENSSL
770 if (ctx != (SSL_CTX *)0)
771 SSL_CTX_free(ctx);
772 if (dh512 != (DH *)0)
773 DH_free(dh512);
774 if (dh1024 != (DH *)0)
775 DH_free(dh1024);
776 if (dh2048 != (DH *)0)
777 DH_free(dh2048);
778 if (dh4096 != (DH *)0)
779 DH_free(dh4096);
780 #endif
781
782 #if USE_IPV6
783 /* clean up addrinfo stucts */
784 freeaddrinfo(bindAddr);
785 freeaddrinfo(bindBaseAddr);
786 #else
787 if (myAddrs != (struct in_addr *)0)
788 free(myAddrs);
789 #endif
790
791 DestroyBreakList();
792 DestroyTaskList();
793 DestroyStrings();
794 DestroyUserList();
795 if (substData != (SUBST *)0)
796 free(substData);
797 }
798
799 void
SummarizeDataStructures(void)800 SummarizeDataStructures(void)
801 {
802 GRPENT *pGE;
803 REMOTE *pRC;
804 ACCESS *pAC;
805 STRING *str;
806 CONSENT *pCE;
807 NAMES *usr;
808 int count;
809 long size;
810 long total = 0;
811 extern STRING *allStrings;
812
813 if (!fDebug)
814 return;
815
816 for (size = 0, count = 0, pGE = pGroups; pGE != (GRPENT *)0;
817 pGE = pGE->pGEnext, count++) {
818 size += sizeof(GRPENT);
819 }
820 CONDDEBUG((1, "Memory Usage (GRPENT objects): %ld (%d)", size, count));
821 total += size;
822
823 for (size = 0, count = 0, pGE = pGroups; pGE != (GRPENT *)0;
824 pGE = pGE->pGEnext) {
825 for (pCE = pGE->pCElist; pCE != (CONSENT *)0;
826 pCE = pCE->pCEnext, count++) {
827 size += strlen(pCE->server) + sizeof(CONSENT);
828 if (pCE->host != (char *)0)
829 size += strlen(pCE->server);
830 if (pCE->device != (char *)0)
831 size += strlen(pCE->device);
832 if (pCE->exec != (char *)0)
833 size += strlen(pCE->exec);
834 if (pCE->master != (char *)0)
835 size += strlen(pCE->master);
836 if (pCE->logfile != (char *)0)
837 size += strlen(pCE->logfile);
838 if (pCE->initcmd != (char *)0)
839 size += strlen(pCE->initcmd);
840 if (pCE->execSlave != (char *)0)
841 size += strlen(pCE->execSlave);
842 if (pCE->motd != (char *)0)
843 size += strlen(pCE->motd);
844 if (pCE->idlestring != (char *)0)
845 size += strlen(pCE->idlestring);
846 if (pCE->replstring != (char *)0)
847 size += strlen(pCE->replstring);
848 if (pCE->tasklist != (char *)0)
849 size += strlen(pCE->tasklist);
850 if (pCE->breaklist != (char *)0)
851 size += strlen(pCE->breaklist);
852 #if HAVE_FREEIPMI
853 if (pCE->username != (char *)0)
854 size += strlen(pCE->username);
855 if (pCE->password != (char *)0)
856 size += strlen(pCE->password);
857 #endif
858 if (pCE->fdlog != (CONSFILE *)0)
859 size += sizeof(CONSFILE);
860 if (pCE->cofile != (CONSFILE *)0)
861 size += sizeof(CONSFILE);
862 if (pCE->initfile != (CONSFILE *)0)
863 size += sizeof(CONSFILE);
864 if (pCE->taskfile != (CONSFILE *)0)
865 size += sizeof(CONSFILE);
866 if (pCE->aliases != (NAMES *)0) {
867 NAMES *n;
868 for (n = pCE->aliases; n != (NAMES *)0; n = n->next) {
869 size += sizeof(NAMES) + strlen(n->name);
870 }
871 }
872 if (pCE->ro) {
873 CONSENTUSERS *u;
874 for (u = pCE->ro; u != (CONSENTUSERS *)0; u = u->next) {
875 size += sizeof(CONSENTUSERS) + strlen(u->user->name);
876 }
877 }
878 if (pCE->rw) {
879 CONSENTUSERS *u;
880 for (u = pCE->rw; u != (CONSENTUSERS *)0; u = u->next) {
881 size += sizeof(CONSENTUSERS) + strlen(u->user->name);
882 }
883 }
884 }
885 }
886 CONDDEBUG((1, "Memory Usage (CONSENT objects): %ld (%d)", size,
887 count));
888 total += size;
889
890 for (size = 0, count = 0, pRC = pRCList; pRC != (REMOTE *)0;
891 pRC = pRC->pRCnext, count++) {
892 size += strlen(pRC->rserver) + strlen(pRC->rhost) + sizeof(REMOTE);
893 if (pRC->aliases != (NAMES *)0) {
894 NAMES *n;
895 for (n = pRC->aliases; n != (NAMES *)0; n = n->next) {
896 size += sizeof(NAMES) + strlen(n->name);
897 }
898 }
899 }
900 CONDDEBUG((1, "Memory Usage (REMOTE objects): %ld (%d)", size, count));
901 total += size;
902
903 for (size = 0, count = 0, pAC = pACList; pAC != (ACCESS *)0;
904 pAC = pAC->pACnext, count++) {
905 size += strlen(pAC->pcwho) + sizeof(ACCESS);
906 }
907 CONDDEBUG((1, "Memory Usage (ACCESS objects): %ld (%d)", size, count));
908 total += size;
909
910 for (size = 0, count = 0, str = allStrings; str != (STRING *)0;
911 str = str->next, count++) {
912 size += str->allocated + sizeof(STRING);
913 }
914 CONDDEBUG((1, "Memory Usage (STRING objects): %ld (%d)", size, count));
915 total += size;
916
917 for (size = 0, count = 0, usr = userList; usr != (NAMES *)0;
918 usr = usr->next, count++) {
919 size += strlen(usr->name) + sizeof(NAMES);
920 }
921 CONDDEBUG((1, "Memory Usage (userList objects): %ld (%d)", size,
922 count));
923 total += size;
924
925 CONDDEBUG((1, "Memory Usage (total): %ld", total));
926 }
927
928 void
DumpDataStructures(void)929 DumpDataStructures(void)
930 {
931 GRPENT *pGE;
932 CONSENT *pCE;
933 REMOTE *pRC;
934 int i;
935 TASKS *t;
936 #if HAVE_FREEIPMI
937 static STRING *tmpString = (STRING *)0;
938 if (tmpString == (STRING *)0)
939 tmpString = AllocString();
940 #endif
941
942 #if HAVE_DMALLOC && DMALLOC_MARK_MAIN
943 CONDDEBUG((1, "DumpDataStructures(): dmalloc / MarkMain"));
944 dmalloc_log_changed(dmallocMarkMain, 1, 0, 1);
945 #endif
946 #define EMPTYSTR(x) x == (char *)0 ? "(null)" : x
947 #define FLAGSTR(x) x == FLAGTRUE ? "true" : (x == FLAGFALSE ? "false" : "unset")
948 if (!fDebug)
949 return;
950
951 SummarizeDataStructures();
952
953 for (pGE = pGroups; pGE != (GRPENT *)0; pGE = pGE->pGEnext) {
954 CONDDEBUG((1,
955 "DumpDataStructures(): group: id=%u port=%hu, pid=%lu, imembers=%d",
956 pGE->id, pGE->port, (unsigned long)pGE->pid,
957 pGE->imembers));
958
959 for (pCE = pGE->pCElist; pCE != (CONSENT *)0; pCE = pCE->pCEnext) {
960 switch (pCE->type) {
961 case DEVICE:
962 CONDDEBUG((1,
963 "DumpDataStructures(): server=%s, type=DEVICE",
964 EMPTYSTR(pCE->server)));
965 CONDDEBUG((1,
966 "DumpDataStructures(): baud=%s, parity=%s, device=%s",
967 pCE->baud->acrate, pCE->parity->key,
968 EMPTYSTR(pCE->device)));
969 break;
970 case EXEC:
971 CONDDEBUG((1,
972 "DumpDataStructures(): server=%s, type=EXEC",
973 EMPTYSTR(pCE->server)));
974 CONDDEBUG((1,
975 "DumpDataStructures(): execSlave=%s, exec=%s, ipid=%lu",
976 EMPTYSTR(pCE->execSlave),
977 EMPTYSTR(pCE->exec),
978 (unsigned long)pCE->ipid));
979 CONDDEBUG((1,
980 "DumpDataStructures(): execuid=%d, execgid=%d",
981 pCE->execuid, pCE->execgid));
982
983 break;
984 #if HAVE_FREEIPMI
985 case IPMI:
986 CONDDEBUG((1,
987 "DumpDataStructures(): server=%s, type=IPMI",
988 EMPTYSTR(pCE->server)));
989 CONDDEBUG((1,
990 "DumpDataStructures(): host=%s, username=%s, password=%s, ipmiprivlevel=%d",
991 EMPTYSTR(pCE->host),
992 EMPTYSTR(pCE->username),
993 EMPTYSTR(pCE->password),
994 pCE->ipmiprivlevel));
995 CONDDEBUG((1,
996 "DumpDataStructures(): ipmiwrkset=%d, ipmiworkaround=%u, ipmiciphersuite=%d",
997 pCE->ipmiwrkset, pCE->ipmiworkaround,
998 pCE->ipmiciphersuite));
999 FmtCtlStr(pCE->ipmikg->string, pCE->ipmikg->used - 1,
1000 tmpString);
1001 CONDDEBUG((1, "DumpDataStructures(): ipmikg=%s",
1002 EMPTYSTR(tmpString->string)));
1003 break;
1004 #endif
1005 case HOST:
1006 CONDDEBUG((1,
1007 "DumpDataStructures(): server=%s, type=HOST",
1008 EMPTYSTR(pCE->server)));
1009 CONDDEBUG((1,
1010 "DumpDataStructures(): host=%s, raw=%s, netport=%hu, port=%hu, telnetState=%d",
1011 EMPTYSTR(pCE->host), FLAGSTR(pCE->raw),
1012 pCE->netport, pCE->port, pCE->telnetState));
1013 break;
1014 case NOOP:
1015 CONDDEBUG((1,
1016 "DumpDataStructures(): server=%s, type=NOOP",
1017 EMPTYSTR(pCE->server)));
1018 break;
1019 case UDS:
1020 CONDDEBUG((1,
1021 "DumpDataStructures(): server=%s, type=UDS",
1022 EMPTYSTR(pCE->server)));
1023 CONDDEBUG((1, "DumpDataStructures(): uds=%s",
1024 EMPTYSTR(pCE->uds)));
1025 break;
1026 case UNKNOWNTYPE:
1027 CONDDEBUG((1,
1028 "DumpDataStructures(): server=%s, type=UNKNOWNTYPE",
1029 EMPTYSTR(pCE->server)));
1030 break;
1031 }
1032 if (pCE->aliases != (NAMES *)0) {
1033 NAMES *n;
1034 for (n = pCE->aliases; n != (NAMES *)0; n = n->next) {
1035 CONDDEBUG((1, "DumpDataStructures(): alias=%s",
1036 n->name));
1037 }
1038 }
1039 CONDDEBUG((1,
1040 "DumpDataStructures(): fup=%d, fronly=%d, logfile=%s, breakNum=%d",
1041 pCE->fup, pCE->fronly, EMPTYSTR(pCE->logfile),
1042 pCE->breakNum));
1043 CONDDEBUG((1,
1044 "DumpDataStructures(): mark=%d, nextMark=%ld, autoReup=%hu, downHard=%s",
1045 pCE->mark, pCE->nextMark, pCE->autoReUp,
1046 FLAGSTR(pCE->downHard)));
1047 CONDDEBUG((1,
1048 "DumpDataStructures(): nolog=%d, cofile=%d, activitylog=%s, breaklog=%s",
1049 pCE->nolog, FileFDNum(pCE->cofile),
1050 FLAGSTR(pCE->activitylog), FLAGSTR(pCE->breaklog)));
1051 CONDDEBUG((1,
1052 "DumpDataStructures(): tasklog=%s, ixon=%s, ixany=%s, ixoff=%s",
1053 FLAGSTR(pCE->tasklog), FLAGSTR(pCE->ixon),
1054 FLAGSTR(pCE->ixany), FLAGSTR(pCE->ixoff)));
1055 CONDDEBUG((1,
1056 "DumpDataStructures(): autoreinit=%s, hupcl=%s, cstopb=%s, ondemand=%s",
1057 FLAGSTR(pCE->autoreinit), FLAGSTR(pCE->hupcl),
1058 FLAGSTR(pCE->cstopb), FLAGSTR(pCE->ondemand)));
1059 #if defined(CRTSCTS)
1060 CONDDEBUG((1, "DumpDataStructures(): crtscts=%s",
1061 FLAGSTR(pCE->crtscts)));
1062 #endif
1063 CONDDEBUG((1,
1064 "DumpDataStructures(): reinitoncc=%s, striphigh=%s",
1065 FLAGSTR(pCE->reinitoncc), FLAGSTR(pCE->striphigh)));
1066 CONDDEBUG((1, "DumpDataStructures(): unloved=%s, login=%s",
1067 FLAGSTR(pCE->unloved), FLAGSTR(pCE->login)));
1068 CONDDEBUG((1,
1069 "DumpDataStructures(): initpid=%lu, initcmd=%s, initfile=%d",
1070 (unsigned long)pCE->initpid, EMPTYSTR(pCE->initcmd),
1071 FileFDNum(pCE->initfile)));
1072 CONDDEBUG((1, "DumpDataStructures(): inituid=%d, initgid=%d",
1073 pCE->inituid, pCE->initgid));
1074 CONDDEBUG((1,
1075 "DumpDataStructures(): motd=%s, idletimeout=%d, idlestring=%s, replstring=%s",
1076 EMPTYSTR(pCE->motd), pCE->idletimeout,
1077 EMPTYSTR(pCE->idlestring),
1078 EMPTYSTR(pCE->replstring)));
1079 CONDDEBUG((1,
1080 "DumpDataStructures(): tasklist=%s, breaklist=%s, taskpid=%lu, taskfile=%d",
1081 EMPTYSTR(pCE->tasklist), EMPTYSTR(pCE->breaklist),
1082 (unsigned long)pCE->taskpid,
1083 FileFDNum(pCE->taskfile)));
1084 if (pCE->ro) {
1085 CONSENTUSERS *u;
1086 for (u = pCE->ro; u != (CONSENTUSERS *)0; u = u->next) {
1087 CONDDEBUG((1, "DumpDataStructures(): ro=%s%s",
1088 (u->not ? "!" : ""), u->user->name));
1089 }
1090 }
1091 if (pCE->rw) {
1092 CONSENTUSERS *u;
1093 for (u = pCE->rw; u != (CONSENTUSERS *)0; u = u->next) {
1094 CONDDEBUG((1, "DumpDataStructures(): rw=%s%s",
1095 (u->not ? "!" : ""), u->user->name));
1096 }
1097 }
1098 CONDDEBUG((1, "DumpDataStructures(): ------"));
1099 }
1100 }
1101 for (pRC = pRCList; (REMOTE *)0 != pRC; pRC = pRC->pRCnext) {
1102 CONDDEBUG((1, "DumpDataStructures(): remote: rserver=%s, rhost=%s",
1103 EMPTYSTR(pRC->rserver), EMPTYSTR(pRC->rhost)));
1104 if (pRC->aliases != (NAMES *)0) {
1105 NAMES *n;
1106 for (n = pRC->aliases; n != (NAMES *)0; n = n->next) {
1107 CONDDEBUG((1, "DumpDataStructures(): alias=%s", n->name));
1108 }
1109 }
1110 }
1111 for (i = 0; i < BREAKLISTSIZE; i++) {
1112 CONDDEBUG((1,
1113 "DumpDataStructures(): break: #%c, string=%s, delay=%d, confirm=%s",
1114 '1' + i + (i > 8 ? BREAKALPHAOFFSET : 0),
1115 EMPTYSTR(breakList[i].seq->string), breakList[i].delay,
1116 FLAGSTR(breakList[i].confirm)));
1117 }
1118 for (t = taskList; t != (TASKS *)0; t = t->next) {
1119 CONDDEBUG((1,
1120 "DumpDataStructures(): task: id=%c, cmd=%s, descr=%s, uid=%d, gid=%d, subst=%s, confirm=%s",
1121 t->id, EMPTYSTR(t->cmd->string),
1122 EMPTYSTR(t->descr->string), t->uid, t->gid,
1123 EMPTYSTR(t->subst), FLAGSTR(t->confirm)));
1124 }
1125 }
1126
1127 /* This makes sure a directory exists and tries to create it if it
1128 * doesn't. returns 0 for success, -1 for error
1129 */
1130 #if USE_UNIX_DOMAIN_SOCKETS
1131 int
VerifyEmptyDirectory(char * d)1132 VerifyEmptyDirectory(char *d)
1133 {
1134 struct stat dstat;
1135 DIR *dir;
1136 struct dirent *de;
1137 # if 0 /* See below */
1138 STRING *path = (STRING *)0;
1139 # endif
1140 int retval = 0;
1141
1142 while (1) {
1143 if (stat(d, &dstat) == -1) {
1144 if (errno == ENOENT) {
1145 if (mkdir(d, 0755) == -1) {
1146 Error("mkdir(%s): %s", d, strerror(errno));
1147 return -1;
1148 }
1149 CONDDEBUG((1, "VerifyEmptyDirectory: created `%s'", d));
1150 continue;
1151 } else {
1152 Error("stat(%s): %s", d, strerror(errno));
1153 return -1;
1154 }
1155 }
1156 if (S_ISDIR(dstat.st_mode))
1157 break;
1158 return -1;
1159 }
1160
1161 /* now make sure it's empty...erase anything you see, etc */
1162 if ((dir = opendir(d)) == (DIR *) 0) {
1163 Error("opendir(%s): %s", d, strerror(errno));
1164 return -1;
1165 }
1166
1167 while ((de = readdir(dir)) != (struct dirent *)0) {
1168 if ((strcmp(de->d_name, ".") == 0) ||
1169 (strcmp(de->d_name, "..") == 0))
1170 continue;
1171 /* we're going to just let the user deal with non-empty directories */
1172 Error("non-empty directory `%s'", d);
1173 retval = -1;
1174 break;
1175 /* this is probably too extreme. if someone happens to point conserver
1176 * at /etc, for example, it could (if running as root) nuke the password
1177 * database, config files, etc. too many important files could be
1178 * shredded with a small typo.
1179 */
1180 # if 0
1181 if (path == (STRING *)0)
1182 path = AllocString();
1183 BuildStringPrint(path, "%s/%s", d, de->d_name);
1184 if (stat(path->string, &dstat) == -1) {
1185 Error("stat(%s): %s", path->string, strerror(errno));
1186 retval = -1;
1187 break;
1188 }
1189 if (S_ISDIR(dstat.st_mode)) {
1190 if (rmdir(path->string) != 0) {
1191 Error("rmdir(%s): %s", path->string, strerror(errno));
1192 retval = -1;
1193 break;
1194 }
1195 } else {
1196 if (unlink(path->string) != 0) {
1197 Error("unlink(%s): %s", path->string, strerror(errno));
1198 retval = -1;
1199 break;
1200 }
1201 }
1202 # endif
1203 }
1204
1205 # if 0 /* See above */
1206 if (path != (STRING *)0)
1207 DestroyString(path);
1208 # endif
1209
1210 /* free dir data structure */
1211 closedir(dir);
1212
1213 return retval;
1214 }
1215 #endif
1216
1217 /* find out where/who we are (ksb)
1218 * parse optons
1219 * read in the config file, open the log file
1220 * spawn the kids to drive the console groups
1221 * become the master server
1222 * shutdown with grace
1223 * exit happy
1224 */
1225 int
main(int argc,char ** argv)1226 main(int argc, char **argv)
1227 {
1228 int i;
1229 FILE *fpConfig = (FILE *)0;
1230 static char acOpts[] = "7a:b:c:C:dDEFhiL:m:M:noO:p:P:RSuU:Vv";
1231 extern int optopt;
1232 extern char *optarg;
1233 struct passwd *pwd;
1234 char *origuser = (char *)0;
1235 char *curuser = (char *)0;
1236 int curuid = 0;
1237 GRPENT *pGE = (GRPENT *)0;
1238 #if !USE_UNIX_DOMAIN_SOCKETS
1239 # if USE_IPV6
1240 int s;
1241 struct addrinfo hints;
1242 # else
1243 # if HAVE_INET_ATON
1244 struct in_addr inetaddr;
1245 # endif
1246 # endif
1247 #endif
1248
1249 isMultiProc = 1; /* make sure stuff has the pid */
1250
1251 thepid = getpid();
1252 if ((char *)0 == (progname = strrchr(argv[0], '/'))) {
1253 progname = argv[0];
1254 } else {
1255 ++progname;
1256 }
1257
1258 setpwent();
1259
1260 /* if we read from stdin (by accident) we don't wanna block.
1261 * we just don't want any more input at this point.
1262 */
1263 close(0);
1264 if (0 != open("/dev/null", O_RDWR, 0644)) {
1265 Error("open(/dev/null): %s", strerror(errno));
1266 Bye(EX_OSFILE);
1267 }
1268 #if HAVE_SETLINEBUF
1269 setlinebuf(stdout);
1270 setlinebuf(stderr);
1271 #endif
1272 #if HAVE_SETVBUF
1273 setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
1274 setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
1275 #endif
1276
1277 /* Initialize the break list */
1278 InitBreakList();
1279
1280 /* prep the config options */
1281 if ((optConf = (CONFIG *)calloc(1, sizeof(CONFIG)))
1282 == (CONFIG *)0)
1283 OutOfMem();
1284 if ((config = (CONFIG *)calloc(1, sizeof(CONFIG)))
1285 == (CONFIG *)0)
1286 OutOfMem();
1287
1288 while (EOF != (i = getopt(argc, argv, acOpts))) {
1289 switch (i) {
1290 case '7':
1291 fStrip = 1;
1292 break;
1293 case 'a':
1294 optConf->defaultaccess = *optarg;
1295 if (isupper((int)(optConf->defaultaccess)))
1296 optConf->defaultaccess =
1297 tolower(optConf->defaultaccess);
1298 switch (optConf->defaultaccess) {
1299 case 'r':
1300 case 'a':
1301 case 't':
1302 break;
1303 default:
1304 Error("unknown access type `%s'", optarg);
1305 Bye(EX_USAGE);
1306 }
1307 break;
1308 case 'b':
1309 if ((optConf->secondaryport = StrDup(optarg)) == (char *)0)
1310 OutOfMem();
1311 break;
1312 case 'c':
1313 #if HAVE_OPENSSL
1314 if ((optConf->sslcredentials =
1315 StrDup(optarg)) == (char *)0)
1316 OutOfMem();
1317 #endif
1318 break;
1319 case 'C':
1320 pcConfig = optarg;
1321 break;
1322 case 'd':
1323 optConf->daemonmode = FLAGTRUE;
1324 break;
1325 case 'D':
1326 fDebug++;
1327 break;
1328 case 'E':
1329 #if HAVE_OPENSSL
1330 optConf->sslrequired = FLAGFALSE;
1331 #endif
1332 break;
1333 case 'F':
1334 fNoautoreup = 1;
1335 break;
1336 case 'h':
1337 Usage(1);
1338 Bye(EX_OK);
1339 case 'i':
1340 fNoinit = 1;
1341 break;
1342 case 'L':
1343 if ((optConf->logfile = StrDup(optarg)) == (char *)0)
1344 OutOfMem();
1345 break;
1346 case 'm':
1347 cMaxMemb = atoi(optarg);
1348 if (cMaxMemb <= 0) {
1349 Error("ignoring invalid -m option (%d <= 0)",
1350 cMaxMemb);
1351 cMaxMemb = MAXMEMB;
1352 }
1353 break;
1354 case 'M':
1355 interface = StrDup(optarg);
1356 break;
1357 case 'n':
1358 /* noop now */
1359 break;
1360 case 'o':
1361 /* try reopening downed consoles on connect */
1362 fReopen = 1;
1363 break;
1364 case 'O':
1365 /* How often to try opening all down consoles, in minutes */
1366 optConf->reinitcheck = atoi(optarg);
1367 break;
1368 case 'p':
1369 if ((optConf->primaryport = StrDup(optarg)) == (char *)0)
1370 OutOfMem();
1371 break;
1372 case 'P':
1373 if ((optConf->passwdfile = StrDup(optarg)) == (char *)0)
1374 OutOfMem();
1375 break;
1376 case 'R':
1377 optConf->redirect = FLAGFALSE;
1378 break;
1379 case 'S':
1380 fSyntaxOnly++;
1381 break;
1382 case 'u':
1383 fAll = 1;
1384 break;
1385 case 'U':
1386 if ((optConf->unifiedlog = StrDup(optarg)) == (char *)0)
1387 OutOfMem();
1388 break;
1389 case 'V':
1390 fVersion = 1;
1391 break;
1392 case 'v':
1393 fVerbose = 1;
1394 break;
1395 case '\?':
1396 Usage(0);
1397 Bye(EX_USAGE);
1398 default:
1399 Error("option %c needs a parameter", optopt);
1400 Bye(EX_USAGE);
1401 }
1402 }
1403
1404 if (fVersion) {
1405 Version();
1406 Bye(EX_OK);
1407 }
1408
1409 Msg(MyVersion());
1410
1411 #if HAVE_GETLOGIN
1412 origuser = getlogin();
1413 #endif
1414 curuid = getuid();
1415
1416 if ((struct passwd *)0 != (pwd = getpwuid(curuid)))
1417 curuser = pwd->pw_name;
1418
1419 /* chuck any empty username */
1420 if (curuser != (char *)0 && curuser[0] == '\000')
1421 curuser = (char *)0;
1422
1423 if (startedMsg == (STRING *)0)
1424 startedMsg = AllocString();
1425 if (curuser == (char *)0)
1426 if (origuser == (char *)0)
1427 BuildStringPrint(startedMsg, "started as uid %d by uid %d",
1428 curuid, curuid);
1429 else
1430 BuildStringPrint(startedMsg, "started as uid %d by `%s'",
1431 curuid, origuser);
1432 else
1433 BuildStringPrint(startedMsg, "started as `%s' by `%s'", curuser,
1434 (origuser == (char *)0) ? curuser : origuser);
1435 endpwent();
1436 Msg("%s", startedMsg->string);
1437
1438 #if HAVE_GETSPNAM && !HAVE_PAM
1439 if (!fSyntaxOnly && (geteuid() != 0)) {
1440 Msg("warning: running as a non-root user - any shadow password usage will most likely fail!");
1441 }
1442 #endif
1443
1444 if (fSyntaxOnly)
1445 Msg("performing configuration file syntax check");
1446
1447 /* must do all this so IsMe() works right */
1448 if (gethostname(myHostname, MAXHOSTNAME) != 0) {
1449 Error("gethostname(): %s", strerror(errno));
1450 Bye(EX_OSERR);
1451 }
1452 #if !USE_IPV6
1453 ProbeInterfaces(bindAddr);
1454 #endif
1455
1456 /* initialize the timers */
1457 for (i = 0; i < T_MAX; i++)
1458 timers[i] = (time_t)0;
1459
1460 /* read the config file */
1461 if ((FILE *)0 == (fpConfig = fopen(pcConfig, "r"))) {
1462 Error("fopen(%s): %s", pcConfig, strerror(errno));
1463 Bye(EX_NOINPUT);
1464 }
1465 ReadCfg(pcConfig, fpConfig);
1466 fclose(fpConfig);
1467
1468 #if !USE_UNIX_DOMAIN_SOCKETS
1469 /* set up the port to bind to */
1470 if (optConf->primaryport != (char *)0)
1471 config->primaryport = StrDup(optConf->primaryport);
1472 else if (pConfig->primaryport != (char *)0)
1473 config->primaryport = StrDup(pConfig->primaryport);
1474 else
1475 config->primaryport = StrDup(defConfig.primaryport);
1476 if (config->primaryport == (char *)0)
1477 OutOfMem();
1478
1479 # if !USE_IPV6
1480 /* Look for non-numeric characters */
1481 for (i = 0; config->primaryport[i] != '\000'; i++)
1482 if (!isdigit((int)config->primaryport[i]))
1483 break;
1484
1485 if (config->primaryport[i] == '\000') {
1486 /* numeric only */
1487 bindPort = atoi(config->primaryport);
1488 } else {
1489 /* non-numeric only */
1490 struct servent *pSE;
1491 if ((struct servent *)0 ==
1492 (pSE = getservbyname(config->primaryport, "tcp"))) {
1493 Error("getservbyname(%s) failed", config->primaryport);
1494 Bye(EX_OSERR);
1495 } else {
1496 bindPort = ntohs((unsigned short)pSE->s_port);
1497 }
1498 }
1499 # endif
1500
1501 /* set up the secondary port to bind to */
1502 if (optConf->secondaryport != (char *)0)
1503 config->secondaryport = StrDup(optConf->secondaryport);
1504 else if (pConfig->secondaryport != (char *)0)
1505 config->secondaryport = StrDup(pConfig->secondaryport);
1506 else
1507 config->secondaryport = StrDup(defConfig.secondaryport);
1508 if (config->secondaryport == (char *)0)
1509 OutOfMem();
1510
1511 # if !USE_IPV6
1512 /* Look for non-numeric characters */
1513 for (i = 0; config->secondaryport[i] != '\000'; i++)
1514 if (!isdigit((int)config->secondaryport[i]))
1515 break;
1516
1517 if (config->secondaryport[i] == '\000') {
1518 /* numeric only */
1519 bindBasePort = atoi(config->secondaryport);
1520 } else {
1521 /* non-numeric only */
1522 struct servent *pSE;
1523 if ((struct servent *)0 ==
1524 (pSE = getservbyname(config->secondaryport, "tcp"))) {
1525 Error("getservbyname(%s) failed", config->secondaryport);
1526 Bye(EX_OSERR);
1527 } else {
1528 bindBasePort = ntohs((unsigned short)pSE->s_port);
1529 }
1530 }
1531 # endif
1532 #endif
1533
1534 #if USE_IPV6
1535 /* set up the address to bind to */
1536 memset(&hints, 0, sizeof(hints));
1537 hints.ai_family = AF_UNSPEC;
1538 hints.ai_socktype = SOCK_STREAM;
1539 hints.ai_flags |= AI_PASSIVE;
1540
1541 /* create list or IPs suitable for primaryport */
1542 s = getaddrinfo(interface, config->primaryport, &hints, &bindAddr);
1543 if (s) {
1544 Error("getaddrinfo(%s): %s", interface, gai_strerror(s));
1545 Bye(EX_OSERR);
1546 }
1547
1548 /* create list or IPs suitable for secondaryport */
1549 s = getaddrinfo(interface, config->secondaryport, &hints,
1550 &bindBaseAddr);
1551 if (s) {
1552 Error("getaddrinfo(%s): %s", interface, gai_strerror(s));
1553 Bye(EX_OSERR);
1554 }
1555 #elif USE_UNIX_DOMAIN_SOCKETS
1556 /* Don't do any redirects if we're purely local
1557 * (but it allows them to see where remote consoles are)
1558 */
1559 optConf->redirect = FLAGFALSE;
1560 if (interface == (char *)0)
1561 interface = UDSDIR;
1562 #else
1563 /* set up the address to bind to */
1564 if (interface == (char *)0 ||
1565 (interface[0] == '*' && interface[1] == '\000'))
1566 bindAddr = INADDR_ANY;
1567 else {
1568 # if HAVE_INET_ATON
1569 if (inet_aton(interface, &inetaddr) == 0) {
1570 Error("inet_aton(%s): %s", interface, "invalid IP address");
1571 Bye(EX_OSERR);
1572 }
1573 bindAddr = inetaddr.s_addr;
1574 # else
1575 bindAddr = inet_addr(interface);
1576 if (bindAddr == (in_addr_t) (-1)) {
1577 Error("inet_addr(%s): %s", interface, "invalid IP address");
1578 Bye(EX_OSERR);
1579 }
1580 # endif
1581 }
1582 if (fDebug) {
1583 struct in_addr ba;
1584 ba.s_addr = bindAddr;
1585 CONDDEBUG((1, "main(): bind address set to `%s'", inet_ntoa(ba)));
1586 }
1587 #endif
1588
1589 if (optConf->passwdfile != (char *)0)
1590 config->passwdfile = StrDup(optConf->passwdfile);
1591 else if (pConfig->passwdfile != (char *)0)
1592 config->passwdfile = StrDup(pConfig->passwdfile);
1593 else
1594 config->passwdfile = StrDup(defConfig.passwdfile);
1595 if (config->passwdfile == (char *)0)
1596 OutOfMem();
1597
1598 if (optConf->logfile != (char *)0)
1599 config->logfile = StrDup(optConf->logfile);
1600 else if (pConfig->logfile != (char *)0)
1601 config->logfile = StrDup(pConfig->logfile);
1602 else
1603 config->logfile = StrDup(defConfig.logfile);
1604 if (config->logfile == (char *)0)
1605 OutOfMem();
1606
1607 if (optConf->reinitcheck != 0)
1608 config->reinitcheck = optConf->reinitcheck;
1609 else if (pConfig->reinitcheck != 0)
1610 config->reinitcheck = pConfig->reinitcheck;
1611 else
1612 config->reinitcheck = defConfig.reinitcheck;
1613
1614 if (optConf->defaultaccess != '\000')
1615 config->defaultaccess = optConf->defaultaccess;
1616 else if (pConfig->defaultaccess != '\000')
1617 config->defaultaccess = pConfig->defaultaccess;
1618 else
1619 config->defaultaccess = defConfig.defaultaccess;
1620
1621 if (optConf->daemonmode != FLAGUNKNOWN)
1622 config->daemonmode = optConf->daemonmode;
1623 else if (pConfig->daemonmode != FLAGUNKNOWN)
1624 config->daemonmode = pConfig->daemonmode;
1625 else
1626 config->daemonmode = defConfig.daemonmode;
1627
1628 if (optConf->redirect != FLAGUNKNOWN)
1629 config->redirect = optConf->redirect;
1630 else if (pConfig->redirect != FLAGUNKNOWN)
1631 config->redirect = pConfig->redirect;
1632 else
1633 config->redirect = defConfig.redirect;
1634
1635 if (optConf->autocomplete != FLAGUNKNOWN)
1636 config->autocomplete = optConf->autocomplete;
1637 else if (pConfig->autocomplete != FLAGUNKNOWN)
1638 config->autocomplete = pConfig->autocomplete;
1639 else
1640 config->autocomplete = defConfig.autocomplete;
1641
1642 if (optConf->loghostnames != FLAGUNKNOWN)
1643 config->loghostnames = optConf->loghostnames;
1644 else if (pConfig->loghostnames != FLAGUNKNOWN)
1645 config->loghostnames = pConfig->loghostnames;
1646 else
1647 config->loghostnames = defConfig.loghostnames;
1648
1649 if (optConf->unifiedlog != (char *)0) {
1650 config->unifiedlog = StrDup(optConf->unifiedlog);
1651 if (config->unifiedlog == (char *)0)
1652 OutOfMem();
1653 } else if (pConfig->unifiedlog != (char *)0) {
1654 config->unifiedlog = StrDup(pConfig->unifiedlog);
1655 if (config->unifiedlog == (char *)0)
1656 OutOfMem();
1657 } else if (defConfig.unifiedlog != (char *)0) {
1658 config->unifiedlog = StrDup(defConfig.unifiedlog);
1659 if (config->unifiedlog == (char *)0)
1660 OutOfMem();
1661 }
1662
1663 if (optConf->initdelay != 0)
1664 config->initdelay = optConf->initdelay;
1665 else if (pConfig->initdelay != 0)
1666 config->initdelay = pConfig->initdelay;
1667 else
1668 config->initdelay = defConfig.initdelay;
1669
1670 #if HAVE_OPENSSL
1671 if (optConf->sslrequired != FLAGUNKNOWN)
1672 config->sslrequired = optConf->sslrequired;
1673 else if (pConfig->sslrequired != FLAGUNKNOWN)
1674 config->sslrequired = pConfig->sslrequired;
1675 else
1676 config->sslrequired = defConfig.sslrequired;
1677
1678 if (optConf->sslreqclientcert != FLAGUNKNOWN)
1679 config->sslreqclientcert = optConf->sslreqclientcert;
1680 else if (pConfig->sslreqclientcert != FLAGUNKNOWN)
1681 config->sslreqclientcert = pConfig->sslreqclientcert;
1682 else
1683 config->sslreqclientcert = defConfig.sslreqclientcert;
1684
1685 if (optConf->sslcredentials != (char *)0)
1686 config->sslcredentials = StrDup(optConf->sslcredentials);
1687 else if (pConfig->sslcredentials != (char *)0)
1688 config->sslcredentials = StrDup(pConfig->sslcredentials);
1689 else
1690 config->sslcredentials = StrDup(defConfig.sslcredentials);
1691
1692 if (optConf->sslcacertificatefile != (char *)0)
1693 config->sslcacertificatefile =
1694 StrDup(optConf->sslcacertificatefile);
1695 else if (pConfig->sslcacertificatefile != (char *)0)
1696 config->sslcacertificatefile =
1697 StrDup(pConfig->sslcacertificatefile);
1698 else
1699 config->sslcacertificatefile =
1700 StrDup(defConfig.sslcacertificatefile);
1701 #endif
1702
1703 #if HAVE_SETPROCTITLE
1704 if (optConf->setproctitle != FLAGUNKNOWN)
1705 config->setproctitle = optConf->setproctitle;
1706 else if (pConfig->setproctitle != FLAGUNKNOWN)
1707 config->setproctitle = pConfig->setproctitle;
1708 else
1709 config->setproctitle = defConfig.setproctitle;
1710 #endif
1711
1712 #if HAVE_DMALLOC && DMALLOC_MARK_MAIN
1713 dmallocMarkMain = dmalloc_mark();
1714 #endif
1715
1716 if (pGroups == (GRPENT *)0 && pRCList == (REMOTE *)0) {
1717 Error("no consoles found in configuration file");
1718 } else if (fSyntaxOnly) {
1719 /* short-circuit */
1720 #if USE_UNIX_DOMAIN_SOCKETS
1721 } else if (VerifyEmptyDirectory(interface) == -1) {
1722 Error("Master(): %s: unusable socket directory", interface);
1723 #endif
1724 } else {
1725 #if HAVE_OPENSSL
1726 /* Prep the SSL layer */
1727 SetupSSL();
1728 #endif
1729 #if HAVE_GSSAPI
1730 SetupGSSAPI();
1731 #endif
1732
1733 if (config->daemonmode == FLAGTRUE)
1734 Daemonize();
1735
1736 ReopenUnifiedlog();
1737
1738 /* if no one can use us we need to come up with a default
1739 */
1740 if (pACList == (ACCESS *)0)
1741 #if USE_IPV6
1742 SetDefAccess();
1743 #else
1744 SetDefAccess(myAddrs, myHostname);
1745 #endif
1746
1747 /* spawn all the children, so fix kids has an initial pid
1748 */
1749 for (pGE = pGroups; pGE != (GRPENT *)0; pGE = pGE->pGEnext) {
1750 if (pGE->imembers == 0)
1751 continue;
1752
1753 Spawn(pGE, -1);
1754 Verbose("group #%d pid %lu on port %hu", pGE->id,
1755 (unsigned long)pGE->pid, pGE->port);
1756 }
1757
1758 #if HAVE_SETPROCTITLE
1759 if (config->setproctitle == FLAGTRUE) {
1760 REMOTE *pRC;
1761 GRPENT *pGE;
1762 int local = 0, remote = 0;
1763 for (pGE = pGroups; pGE != (GRPENT *)0; pGE = pGE->pGEnext)
1764 local += pGE->imembers;
1765 for (pRC = pRCList; (REMOTE *)0 != pRC; pRC = pRC->pRCnext)
1766 remote++;
1767 setproctitle("master: port %hu, %d local, %d remote",
1768 # if USE_IPV6
1769 config->primaryport,
1770 # elif USE_UNIX_DOMAIN_SOCKETS
1771 0,
1772 # else
1773 bindPort,
1774 # endif
1775 local, remote);
1776 }
1777 #endif
1778
1779 if (fVerbose) {
1780 ACCESS *pACtmp;
1781 for (pACtmp = pACList; pACtmp != (ACCESS *)0;
1782 pACtmp = pACtmp->pACnext) {
1783 Verbose("access type `%c' for `%s'", pACtmp->ctrust,
1784 pACtmp->pcwho);
1785 }
1786 }
1787
1788 pRCUniq = FindUniq(pRCList);
1789
1790 /* output unique console server peers?
1791 */
1792 if (fVerbose) {
1793 REMOTE *pRC;
1794 for (pRC = pRCUniq; (REMOTE *)0 != pRC; pRC = pRC->pRCuniq) {
1795 Verbose("peer server on `%s'", pRC->rhost);
1796 }
1797 }
1798
1799 fflush(stdout);
1800 fflush(stderr);
1801 Master();
1802
1803 /* stop putting kids back, and shoot them
1804 */
1805 SimpleSignal(SIGCHLD, SIG_DFL);
1806 SignalKids(SIGTERM);
1807 }
1808
1809 if (unifiedlog != (CONSFILE *)0)
1810 FileClose(&unifiedlog);
1811
1812 DumpDataStructures();
1813
1814 Msg("terminated");
1815 endpwent();
1816 if (fSyntaxOnly && fErrorPrinted)
1817 Bye(EX_DATAERR);
1818 else
1819 Bye(EX_OK);
1820 return EX_OK; /* never gets here clears the compiler warning */
1821 }
1822