Files: e492c2808c90ee151362420d6ac0b0d22cb943db / systemd-sslh-generator.c
3925 bytesRaw
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | static char* resolve_listen(const char *hostname, const char *port) { |
8 | |
9 | /* Need room in the strcat for \0 and : |
10 | * the format in the socket unit file is hostname:port */ |
11 | char *conn = (char*)malloc(strlen(hostname)+strlen(port)+2); |
12 | strcpy(conn, hostname); |
13 | strcat(conn, ":"); |
14 | strcat(conn, port); |
15 | |
16 | return conn; |
17 | |
18 | } |
19 | |
20 | |
21 | static int get_listen_from_conf(const char *filename, char **listen) { |
22 | |
23 | config_t config; |
24 | config_setting_t *setting, *addr; |
25 | const char *hostname, *port; |
26 | int len = 0; |
27 | |
28 | /* look up the listen stanzas in the config file so these |
29 | * can be used in the socket file generated */ |
30 | |
31 | config_init(&config); |
32 | if (config_read_file(&config, filename) == CONFIG_FALSE) { |
33 | /* we don't care if file is missing, skip it */ |
34 | if (config_error_line(&config) != 0) { |
35 | fprintf(stderr, "%s:%d:%s\n", |
36 | filename, |
37 | config_error_line(&config), |
38 | config_error_text(&config)); |
39 | return -1; |
40 | } |
41 | } else { |
42 | setting = config_lookup(&config, "listen"); |
43 | if (setting) { |
44 | len = config_setting_length(setting); |
45 | for (int i = 0; i < len; i++) { |
46 | addr = config_setting_get_elem(setting, i); |
47 | if (! (config_setting_lookup_string(addr, "host", &hostname) && |
48 | config_setting_lookup_string(addr, "port", &port))) { |
49 | fprintf(stderr, |
50 | "line %d:Incomplete specification (hostname and port required)\n", |
51 | config_setting_source_line(addr)); |
52 | return -1; |
53 | } else { |
54 | |
55 | listen[i] = malloc(strlen(resolve_listen(hostname, port))); |
56 | strcpy(listen[i], resolve_listen(hostname, port)); |
57 | } |
58 | } |
59 | } |
60 | } |
61 | |
62 | return len; |
63 | |
64 | } |
65 | |
66 | static int write_socket_unit(FILE *socket, char **listen, int num_addr, const char *source) { |
67 | |
68 | fprintf(socket, |
69 | "# Automatically generated by systemd-sslh-generator\n\n" |
70 | "[Unit]\n" |
71 | "Before=sslh.service\n" |
72 | "SourcePath=%s\n" |
73 | "Documentation=man:sslh(8) man:systemd-sslh-generator(8)\n\n" |
74 | "[Socket]\n" |
75 | "FreeBind=true\n", |
76 | source); |
77 | |
78 | for (int i = 0; i < num_addr; i++) { |
79 | fprintf(socket, "ListenStream=%s\n", listen[i]); |
80 | } |
81 | |
82 | return 0; |
83 | } |
84 | |
85 | static int gen_sslh_config(char *runtime_unit_dir) { |
86 | |
87 | char *sslh_conf; |
88 | int num_addr; |
89 | FILE *config; |
90 | char **listen; |
91 | FILE *runtime_conf_fd = stdout; |
92 | const char *unit_file; |
93 | |
94 | /* There are two default locations so check both with first given preference */ |
95 | sslh_conf = "/etc/sslh.cfg"; |
96 | |
97 | config = fopen(sslh_conf, "r"); |
98 | if (config == NULL) { |
99 | sslh_conf="/etc/sslh/sslh.cfg"; |
100 | config = fopen(sslh_conf, "r"); |
101 | if (config == NULL) { |
102 | return -1; |
103 | } |
104 | } |
105 | |
106 | fclose(config); |
107 | |
108 | |
109 | num_addr = get_listen_from_conf(sslh_conf, listen); |
110 | if (num_addr < 0) |
111 | return -1; |
112 | |
113 | /* If this is run by systemd directly write to the location told to |
114 | * otherwise write to standard out so that it's trivial to check what |
115 | * will be written */ |
116 | if (runtime_unit_dir != "") { |
117 | unit_file = "/sslh.socket"; |
118 | size_t uf_len = strlen(unit_file); |
119 | size_t runtime_len = strlen(runtime_unit_dir) + uf_len + 1; |
120 | char *runtime_conf = malloc(runtime_len); |
121 | strcpy(runtime_conf, runtime_unit_dir); |
122 | strcat(runtime_conf, unit_file); |
123 | runtime_conf_fd = fopen(runtime_conf, "w"); |
124 | } |
125 | |
126 | |
127 | return write_socket_unit(runtime_conf_fd, listen, num_addr, sslh_conf); |
128 | |
129 | } |
130 | |
131 | int main(int argc, char *argv[]){ |
132 | |
133 | int r = 0; |
134 | int k; |
135 | char *runtime_unit_dest = ""; |
136 | |
137 | if (argc > 1 && (argc != 4) ) { |
138 | printf("This program takes three or no arguments.\n"); |
139 | return -1; |
140 | } |
141 | |
142 | if (argc > 1) |
143 | runtime_unit_dest = argv[1]; |
144 | |
145 | k = gen_sslh_config(runtime_unit_dest); |
146 | if (k < 0) |
147 | r = k; |
148 | |
149 | return r < 0 ? -1 : 0; |
150 | |
151 | } |
152 | |
153 | |
154 |
Built with git-ssb-web