1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25#include <stdio.h>
26#include <ctype.h>
27#include <stdlib.h>
28#include <string.h>
29#include <unistd.h>
30#include <signal.h>
31#include <errno.h>
32#include <fcntl.h>
33#include <syslog.h>
34#include <netdb.h>
35#include <paths.h>
36#include <sys/queue.h>
37
38#include <sys/param.h>
39#include <sys/types.h>
40#include <sys/wait.h>
41#include <sys/time.h>
42#include <sys/resource.h>
43#include <sys/stat.h>
44#include <sys/socket.h>
45#include <netinet/in.h>
46#include <arpa/inet.h>
47#include <net/if.h>
48
49#include <CoreFoundation/CoreFoundation.h>
50#include <SystemConfiguration/SystemConfiguration.h>
51#include "../../Family/if_ppplink.h"
52
53#include "vpnd.h"
54#include "vpnoptions.h"
55#include "cf_utils.h"
56#include "vpnplugins.h"
57#include "pppoptions.h"
58#include "ipsecoptions.h"
59#include "ipsec_utils.h"
60#include "RASSchemaDefinitions.h"
61
62static char*	default_log_path = "/var/log/" DAEMON_NAME ".log";
63static u_char*  empty_str = (u_char*)"";
64
65
66static void usage(FILE *fp, const char *argv0);
67static int process_server_prefs(struct vpn_params *params);
68static int process_interface_prefs(struct vpn_params *params);
69
70
71//-----------------------------------------------------------------------------
72//	process_options
73//-----------------------------------------------------------------------------
74int process_options(struct vpn_params *params, int argc, char *argv[])
75{
76
77    char* 		argv0 = argv[0];
78    char* 		args = "dhnxi:";
79    char		c;
80
81    /* initialize generic portion */
82	params->max_sessions = 0;
83    params->debug = 0;
84	params->log_verbose = 0;
85    params->daemonize = 1;
86    params->serverIDRef = 0;
87    params->serverRef = 0;
88    params->server_id = 0;
89    params->server_type = -1;
90    params->storeRef = 0;
91    params->next_arg_index = 0;
92    params->log_path[0] = 0;
93
94    // Process command line arguments, if any
95    while ((opterr == 1) && (c = getopt(argc, argv, args)) != EOF) {
96        switch (c) {
97            case 'h':
98                usage (stdout, argv0);
99                exit (0);
100
101            case 'n':
102                set_terminate();
103                /* FALLTHRU */
104
105            case 'd':
106                params->debug = 1;
107                break;
108
109            case 'x':
110                params->daemonize = 0;
111                break ;
112
113            case 'i':
114                params->server_id = optarg;
115                break ;
116
117            default:
118                usage(stderr, argv0);
119                return -1;
120        }
121    }
122
123	/* init ppp portion */
124	ppp_process_options(params);
125
126	/* init ipsec portion */
127	ipsec_process_options(params);
128
129    return 0;
130}
131
132// ----------------------------------------------------------------------------
133//	get_active_server
134// ----------------------------------------------------------------------------
135CFArrayRef get_active_servers(struct vpn_params *params)
136{
137    SCPreferencesRef 		prefs = 0;
138    CFPropertyListRef		active_servers;
139    CFArrayRef                  arrayCopy = 0;
140    char 			pathStr[MAXPATHLEN];
141
142    // open the prefs file
143    prefs = SCPreferencesCreate(0, CFSTR("vpnd"), kRASServerPrefsFileName);
144    if (prefs == NULL) {
145        CFStringGetCString(kRASServerPrefsFileName, pathStr, MAXPATHLEN, kCFStringEncodingMacRoman);
146        vpnlog(LOG_ERR, "Unable to read vpnd prefs file '%s'\n", pathStr);
147        return 0;
148    }
149    // get active servers list from the plist
150    active_servers = SCPreferencesGetValue(prefs, kRASActiveServers);
151    if (active_servers && isArray(active_servers))
152        if (CFArrayGetCount(active_servers) > 0)
153            arrayCopy = CFArrayCreateCopy(0, active_servers);
154    CFRelease(prefs);
155    return arrayCopy;
156}
157
158// ----------------------------------------------------------------------------
159//	process_prefs
160// ----------------------------------------------------------------------------
161int process_prefs(struct vpn_params *params)
162{
163
164    char 			pathStr[MAXPATHLEN];
165    SCPreferencesRef 		prefs = 0;
166    CFPropertyListRef		servers_list;
167
168    char 			text[512] = "";
169
170    // open the prefs file
171    prefs = SCPreferencesCreate(0, CFSTR("vpnd"), kRASServerPrefsFileName);
172    if (prefs == NULL) {
173        CFStringGetCString(kRASServerPrefsFileName, pathStr, MAXPATHLEN, kCFStringEncodingMacRoman);
174        snprintf(text, sizeof(text), "Unable to read vpnd prefs file '%s'\n", pathStr);
175        goto fail;
176    }
177    // get servers list from the plist
178    servers_list = SCPreferencesGetValue(prefs, kRASServers);
179    if (servers_list == NULL) {
180        snprintf(text, sizeof(text), "Could not get servers dictionary\n");
181        goto fail;
182    }
183    // retrieve the information for the given Server ID
184    params->serverIDRef = CFStringCreateWithCString(0, params->server_id, kCFStringEncodingMacRoman);
185    if (params->serverIDRef == NULL) {
186        snprintf(text, sizeof(text), "Could not create CFString for server ID\n");
187        goto fail;
188    }
189    params->serverRef = CFDictionaryGetValue(servers_list, params->serverIDRef);
190    if (params->serverRef == NULL || isDictionary(params->serverRef) == 0) {
191        snprintf(text, sizeof(text), "Server ID '%.64s' invalid\n", params->server_id);
192        params->serverRef = 0;
193        goto fail;
194    }
195    CFRetain(params->serverRef);
196    CFRelease(prefs);
197    prefs = 0;
198
199    // process the dictionaries
200    if (process_server_prefs(params))
201        goto fail;
202    if (process_interface_prefs(params))
203        goto fail;
204
205	switch (params->server_type) {
206		case SERVER_TYPE_PPP:
207			if (ppp_process_prefs(params)) {
208				snprintf(text, sizeof(text), "Error while reading PPP preferences\n");
209				goto fail;
210			}
211			break;
212		case SERVER_TYPE_IPSEC:
213			if (ipsec_process_prefs(params)) {
214				snprintf(text, sizeof(text), "Error while reading IPSec preferences\n");
215				goto fail;
216			}
217			break;
218	}
219
220    return 0;
221
222fail:
223    vpnlog(LOG_ERR, text[0] ? text : "Error while reading preferences\n");
224    if (params->serverIDRef) {
225        CFRelease(params->serverIDRef);
226        params->serverIDRef = 0;
227    }
228    if (params->serverRef) {
229        CFRelease(params->serverRef);
230        params->serverRef = 0;
231    }
232    if (prefs)
233        CFRelease(prefs);
234    return -1;
235}
236
237
238
239//-----------------------------------------------------------------------------
240//	process_server_prefs
241//-----------------------------------------------------------------------------
242static int process_server_prefs(struct vpn_params *params)
243{
244    u_int32_t		lval, len;
245    u_char            str[MAXPATHLEN];
246	int				err ;
247	struct hostent	*hostent;
248
249    get_int_option(params->serverRef, kRASEntServer, kRASPropServerMaximumSessions, &lval, 0);
250    if (lval)
251        params->max_sessions = lval;
252	len = sizeof(str);
253    get_str_option(params->serverRef, kRASEntServer, kRASPropServerLogfile, str, sizeof(str), &len, (u_char*)default_log_path);
254    if (str[0])
255        memcpy(params->log_path, str, len + 1);
256
257    get_int_option(params->serverRef, kRASEntServer, kRASPropServerVerboseLogging, &lval, 0);
258    if (lval)
259        params->log_verbose = lval;
260
261	// Load balancing parameters
262	get_int_option(params->serverRef, kRASEntServer, kRASPropServerLoadBalancingEnabled, &lval, 0);
263	if (lval) {
264		params->lb_enable = 1;
265
266		// will determine the interface from the cluster address
267		//len = sizeof(str);
268		//get_str_option(params->serverRef, kRASEntServer, kRASPropServerLoadBalancingInterface, str, sizeof(str), &len, "en1");
269		//strncpy(params->lb_interface, str, sizeof(params->lb_interface));
270
271		// is priority really useful ?
272		//get_int_option(params->serverRef, kRASEntServer, kRASPropServerLoadBalancingPriority, &lval, 5);
273		//if (lval < 1) lval = 1;
274		//else if (lval > LB_MAX_PRIORITY) lval = LB_MAX_PRIORITY;
275		//params->lb_priority = lval;
276
277		get_int_option(params->serverRef, kRASEntServer, kRASPropServerLoadBalancingPort, &lval, LB_DEFAULT_PORT);
278		params->lb_port = htons(lval);
279		len = sizeof(str);
280		get_str_option(params->serverRef, kRASEntServer, kRASPropServerLoadBalancingAddress, str, sizeof(str), &len, empty_str);
281		// ask the system to look up the given name.
282		hostent = getipnodebyname ((char*)str, AF_INET, 0, &err);
283		if (!hostent) {
284			vpnlog(LOG_ERR, "Incorrect Load Balancing address found '%s'\n", str);
285			params->lb_enable = 0;
286
287		}
288		else {
289			struct sockaddr_in src, dst;
290
291			params->lb_cluster_address = *(struct in_addr *)hostent->h_addr_list[0];
292			freehostent(hostent);
293
294			bzero(&dst, sizeof(dst));
295			dst.sin_family = PF_INET;
296			dst.sin_len = sizeof(dst);
297			dst.sin_addr = params->lb_cluster_address;
298
299			// look for the interface and primary address of the cluster address
300			if (get_route_interface((struct sockaddr *)&src, (struct sockaddr *)&dst, params->lb_interface)) {
301
302				vpnlog(LOG_ERR, "Cannot get load balancing redirect address and interface (errno = %d)\n", errno);
303				params->lb_enable = 0;
304			}
305
306			params->lb_redirect_address = src.sin_addr;
307
308
309		}
310	}
311
312    return 0;
313}
314
315//-----------------------------------------------------------------------------
316//	process_interface_prefs
317//-----------------------------------------------------------------------------
318static int process_interface_prefs(struct vpn_params *params)
319{
320    CFStringRef 	str = 0;
321    CFDictionaryRef	dict;
322
323    //  get type/subtype of server
324    dict = CFDictionaryGetValue(params->serverRef, kRASEntInterface);
325    if (!isDictionary(dict)) {
326		vpnlog(LOG_ERR, "No Interface dictionary found\n");
327		return -1;
328	}
329
330	str  = CFDictionaryGetValue(dict, kRASPropInterfaceType);
331	if (!isString(str)) {
332		vpnlog(LOG_ERR, "No Interface type found\n");
333		return -1;
334	}
335
336	if (CFStringCompare(str, kRASValInterfaceTypePPP, 0) == kCFCompareEqualTo)
337		params->server_type = SERVER_TYPE_PPP;
338	else if (CFStringCompare(str, kRASValInterfaceTypeIPSec, 0) == kCFCompareEqualTo)
339		params->server_type = SERVER_TYPE_IPSEC;
340	else {
341		vpnlog(LOG_ERR, "Incorrect server type found\n");
342		return -1;
343	}
344
345	return 0;
346}
347
348//-----------------------------------------------------------------------------
349//	publish_state
350//-----------------------------------------------------------------------------
351int publish_state(struct vpn_params* params)
352{
353    CFMutableDictionaryRef	dict;
354    CFStringRef			key;
355    int 			val;
356    CFNumberRef			num;
357
358    if (params->storeRef == 0)
359        return 0;
360
361    /* Interface information */
362    key = SCDynamicStoreKeyCreate(0, CFSTR("%@/%@/%@/%@/%s"),
363                kSCDynamicStoreDomainState,
364                kSCCompNetwork, kRASRemoteAccessServer, params->serverIDRef, "Interface");
365    if (key) {
366        dict = CFDictionaryCreateMutable(0, 0,
367                        &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
368        if (dict) {
369			switch (params->server_type) {
370				case SERVER_TYPE_PPP:
371					CFDictionarySetValue(dict, kRASPropInterfaceType,  kRASValInterfaceTypePPP);
372					CFDictionarySetValue(dict, kRASPropInterfaceSubType,  params->serverSubTypeRef);
373					break;
374				case SERVER_TYPE_IPSEC:
375					CFDictionarySetValue(dict, kRASPropInterfaceType,  kRASValInterfaceTypeIPSec);
376					break;
377			}
378            SCDynamicStoreAddTemporaryValue(params->storeRef, key, dict);
379            CFRelease(dict);
380        }
381        CFRelease(key);
382    }
383
384    /* Server information */
385    key = SCDynamicStoreKeyCreate(0, CFSTR("%@/%@/%@/%@/%s"),
386                kSCDynamicStoreDomainState,
387                kSCCompNetwork, kRASRemoteAccessServer, params->serverIDRef, "Server");
388    if (key) {
389        dict = CFDictionaryCreateMutable(0, 0,
390                        &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
391        if (dict) {
392            val = getpid();
393            num = CFNumberCreate(0, kCFNumberIntType, &val);
394            if (num) {
395                CFDictionarySetValue(dict, CFSTR("pid"),  num);
396                SCDynamicStoreAddTemporaryValue(params->storeRef, key, dict);
397                CFRelease(num);
398            }
399            CFRelease(dict);
400        }
401        CFRelease(key);
402    }
403
404    return 1;
405}
406
407//-----------------------------------------------------------------------------
408//	open_dynamic_store
409//-----------------------------------------------------------------------------
410void open_dynamic_store(struct vpn_params* params)
411{
412    params->storeRef = SCDynamicStoreCreate(0, CFSTR("vpnd"), 0, 0);
413}
414
415//-----------------------------------------------------------------------------
416//	close_dynamic_store
417//-----------------------------------------------------------------------------
418void close_dynamic_store(struct vpn_params* params)
419{
420    if (params->storeRef) {
421		CFRelease(params->storeRef);
422		params->storeRef = NULL;
423	}
424
425}
426
427//-----------------------------------------------------------------------------
428//	check_conflicts
429//-----------------------------------------------------------------------------
430int check_conflicts(struct vpn_params *params)
431{
432
433    if (params->storeRef == 0)
434        return 0;
435
436	switch (params->server_type) {
437		case SERVER_TYPE_PPP:
438			return ppp_check_conflicts(params);
439
440		case SERVER_TYPE_IPSEC:
441			return 0;
442	}
443
444    return 0;
445}
446
447//-----------------------------------------------------------------------------
448//	kill_orphans
449//-----------------------------------------------------------------------------
450int kill_orphans(struct vpn_params* params)
451{
452
453    if (params->storeRef == 0)
454        return 0;
455
456	switch (params->server_type) {
457		case SERVER_TYPE_PPP:
458			return ppp_kill_orphans(params);
459
460		case SERVER_TYPE_IPSEC:
461			return 0;
462	}
463
464    return 0;
465}
466
467//-----------------------------------------------------------------------------
468//	add_builtin_plugin for non plugin based connection
469//-----------------------------------------------------------------------------
470int add_builtin_plugin(struct vpn_params* params, void *channel)
471{
472
473	switch (params->server_type) {
474		case SERVER_TYPE_PPP:
475			/* ppp connection are plugin based */
476			return -1;
477
478		case SERVER_TYPE_IPSEC:
479			return ipsec_add_builtin_plugin(params, channel);
480	}
481
482    return -1;
483}
484
485// ----------------------------------------------------------------------------
486//	usage
487// ----------------------------------------------------------------------------
488static void usage(FILE *fp, const char *argv0)
489{
490	static const char* 	szpUsage =
491		"Usage:\t%s [-dhnx] [-i serverID]\n"
492		"	-h		this message\n"
493		"	-x		does not move to background\n"
494		"	-d		enable debug mode\n"
495		"	-n		same as -d but terminates after validation\n"
496		"	-i		server ID for this server (ex: com.apple.ppp.l2tp)\n"
497		;
498    fprintf (fp, szpUsage, argv0);
499}
500
501//-----------------------------------------------------------------------------
502//	plugin_exists - checks to see if the given plugin exists.
503//-----------------------------------------------------------------------------
504int plugin_exists(const char *inPath)
505{
506    struct stat	sbTemp, *sbpTemp = &sbTemp;
507    char path[MAXPATHLEN];
508
509    path[0] = 0;
510    if (inPath[0] != '/')
511        strlcpy(path, PLUGINS_DIR, sizeof(path));
512    strlcat(path, inPath, sizeof(path));
513
514    if (stat(path, sbpTemp))
515            return 0;
516    //if (!S_ISREG (sbpTemp->st_mode)) {
517     //   errno = ENOENT;
518     //   return-1;
519   // }
520    return 1;
521}
522
523//-----------------------------------------------------------------------------
524//	validate_ipstring
525//-----------------------------------------------------------------------------
526char* validate_ip_string(const char *inIPString, char *outIPString, size_t outSize)
527{
528
529    int		nErr ;
530    char*	outIP;
531
532    if (!inIPString)
533            return 0;
534    if (!*inIPString)
535            return 0;
536    if (outSize < 16)
537            return 0;
538
539    // First, ask the system to look up the given name.
540    struct hostent	*hesp = getipnodebyname (inIPString, AF_INET, 0, &nErr);
541    if (hesp == NULL)
542        return 0;
543    // Convert the returned info to dotted decimal string.
544    outIP = (char*)inet_ntop(AF_INET, hesp->h_addr_list[0], outIPString, outSize);
545    freehostent (hesp);
546    return outIP;
547}
548
549// ----------------------------------------------------------------------------
550//	addparam
551// ----------------------------------------------------------------------------
552
553void addparam(char **arg, u_int32_t *argi, char *param)
554{
555    int len = strlen(param);
556
557    if (len && (arg[*argi] = malloc(len + 1))) {
558        strlcpy(arg[*argi], param, (len + 1));
559        (*argi)++;
560    }
561}
562
563// ----------------------------------------------------------------------------
564//	addintparam
565// ----------------------------------------------------------------------------
566void addintparam(char **arg, u_int32_t *argi, char *param, u_int32_t val)
567{
568    char	str[32];
569
570    addparam(arg, argi, param);
571    snprintf(str, sizeof(str), "%d", val);
572    addparam(arg, argi, str);
573}
574
575// ----------------------------------------------------------------------------
576//	addstrparam
577// ----------------------------------------------------------------------------
578void addstrparam(char **arg, u_int32_t *argi, char *param, char *val)
579{
580
581    addparam(arg, argi, param);
582    addparam(arg, argi, val);
583}
584
585