1 /*
2 * Copyright (C) 2014-2017 Red Hat
3 * Copyright (C) 2014-2018 Nikos Mavrogiannopoulos
4 *
5 * Author: Nikos Mavrogiannopoulos
6 *
7 * This file is part of ocserv.
8 *
9 * ocserv is free software: you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * ocserv is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include <config.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <time.h>
28 #include <errno.h>
29 #include <signal.h>
30 #include <c-ctype.h>
31 #include <ctl.h>
32 #include <ctl.pb-c.h>
33 #include <occtl/occtl.h>
34 #include <common.h>
35 #include <c-strcase.h>
36 #include <arpa/inet.h>
37 #include <system.h>
38 #include <termios.h>
39 #include <unistd.h>
40 #include <minmax.h>
41 #include <sys/select.h>
42 #include <sys/time.h>
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <sys/socket.h>
46 #include <sys/un.h>
47 #include <assert.h>
48 #include "hex.h"
49 #include "geoip.h"
50 #include <vpn.h>
51 #include <base64-helper.h>
52
53 /* In JSON output include fields which were no longer available after 0.11.7
54 */
55 #undef OCSERV_0_11_6_COMPAT
56
57 static
58 int common_info_cmd(UserListRep *args, FILE *out, cmd_params_st *params);
59 static
60 int session_info_cmd(void *ctx, SecmListCookiesReplyMsg * args, FILE *out,
61 cmd_params_st *params,
62 const char *lsid, unsigned all);
63
64 struct unix_ctx {
65 int fd;
66 int is_open;
67 const char *socket_file;
68 };
69
70 static uint8_t msg_map[] = {
71 [CTL_CMD_STATUS] = CTL_CMD_STATUS_REP,
72 [CTL_CMD_RELOAD] = CTL_CMD_RELOAD_REP,
73 [CTL_CMD_STOP] = CTL_CMD_STOP_REP,
74 [CTL_CMD_LIST] = CTL_CMD_LIST_REP,
75 [CTL_CMD_LIST_COOKIES] = CTL_CMD_LIST_COOKIES_REP,
76 [CTL_CMD_LIST_BANNED] = CTL_CMD_LIST_BANNED_REP,
77 [CTL_CMD_USER_INFO] = CTL_CMD_LIST_REP,
78 [CTL_CMD_TOP] = CTL_CMD_LIST_REP,
79 [CTL_CMD_ID_INFO] = CTL_CMD_LIST_REP,
80 [CTL_CMD_DISCONNECT_NAME] = CTL_CMD_DISCONNECT_NAME_REP,
81 [CTL_CMD_DISCONNECT_ID] = CTL_CMD_DISCONNECT_ID_REP,
82 [CTL_CMD_UNBAN_IP] = CTL_CMD_UNBAN_IP_REP,
83 };
84
85 struct cmd_reply_st {
86 unsigned cmd;
87 uint8_t *data;
88 unsigned data_size;
89 };
90
free_reply(struct cmd_reply_st * rep)91 static void free_reply(struct cmd_reply_st *rep)
92 {
93 talloc_free(rep->data);
94 }
95
init_reply(struct cmd_reply_st * rep)96 static void init_reply(struct cmd_reply_st *rep)
97 {
98 if (rep)
99 rep->data = NULL;
100 }
101
102 /* sends a message and returns the reply */
103 static
send_cmd(struct unix_ctx * ctx,unsigned cmd,const void * data,pack_size_func get_size,pack_func pack,struct cmd_reply_st * rep)104 int send_cmd(struct unix_ctx *ctx, unsigned cmd, const void *data,
105 pack_size_func get_size, pack_func pack,
106 struct cmd_reply_st *rep)
107 {
108 int e, ret;
109 uint32_t length32 = 0;
110 void *packed = NULL;
111 uint8_t rcmd;
112
113 ret = send_msg(ctx, ctx->fd, cmd, data, get_size, pack);
114 if (ret < 0) {
115 e = errno;
116 fprintf(stderr, "writev: %s\n", strerror(e));
117 ret = -1;
118 goto fail;
119 }
120
121 if (rep != NULL) {
122 ret = recv_msg_headers(ctx->fd, &rcmd, DEFAULT_TIMEOUT);
123 if (ret < 0) {
124 /*e = errno;
125 fprintf(stderr, "read: %s\n", strerror(e));*/
126 ret = -1;
127 goto fail;
128 }
129
130 rep->cmd = rcmd;
131 length32 = ret;
132
133 if (msg_map[cmd] != rep->cmd) {
134 fprintf(stderr, "Unexpected message '%d', expected '%d'\n", (int)rep->cmd, (int)msg_map[cmd]);
135 ret = -1;
136 goto fail;
137 }
138
139 rep->data_size = length32;
140 rep->data = talloc_size(ctx, length32);
141 if (rep->data == NULL) {
142 fprintf(stderr, "memory error\n");
143 ret = -1;
144 goto fail;
145 }
146
147 ret = force_read_timeout(ctx->fd, rep->data, length32, DEFAULT_TIMEOUT);
148 if (ret == -1) {
149 e = errno;
150 talloc_free(rep->data);
151 rep->data = NULL;
152 fprintf(stderr, "read: %s\n", strerror(e));
153 ret = -1;
154 goto fail;
155 }
156 }
157
158 ret = 0;
159 fail:
160 talloc_free(packed);
161 return ret;
162 }
163
164 static
connect_to_ocserv(const char * socket_file)165 int connect_to_ocserv (const char *socket_file)
166 {
167 int sd, ret, e;
168 struct sockaddr_un sa;
169
170 if (socket_file == NULL)
171 socket_file = OCCTL_UNIX_SOCKET;
172
173 memset(&sa, 0, sizeof(sa));
174 sa.sun_family = AF_UNIX;
175 snprintf(sa.sun_path, sizeof(sa.sun_path), "%s", socket_file);
176
177 sd = socket(AF_UNIX, SOCK_STREAM, 0);
178 if (sd == -1) {
179 e = errno;
180 fprintf(stderr, "error opening socket: %s\n", strerror(e));
181 return -1;
182 }
183
184 ret = connect(sd, (struct sockaddr *)&sa, sizeof(sa));
185 if (ret == -1) {
186 e = errno;
187 fprintf(stderr, "error connecting to ocserv socket '%s': %s\n",
188 sa.sun_path, strerror(e));
189 ret = -1;
190 goto error;
191 }
192
193 return sd;
194 error:
195 close(sd);
196 return ret;
197
198 }
199
handle_status_cmd(struct unix_ctx * ctx,const char * arg,cmd_params_st * params)200 int handle_status_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
201 {
202 int ret;
203 struct cmd_reply_st raw;
204 StatusRep *rep;
205 char str_since[64];
206 char buf[MAX_TMPSTR_SIZE];
207 time_t t;
208 struct tm *tm, _tm;
209 PROTOBUF_ALLOCATOR(pa, ctx);
210
211 init_reply(&raw);
212
213 print_start_block(stdout, params);
214 if (NO_JSON(params)) {
215 printf("Note: the printed statistics are not real-time; session time\n");
216 printf("as well as RX and TX data are updated on user disconnect\n");
217 }
218
219 ret = send_cmd(ctx, CTL_CMD_STATUS, NULL, NULL, NULL, &raw);
220 if (ret < 0) {
221 goto error_status;
222 }
223
224 rep = status_rep__unpack(&pa, raw.data_size, raw.data);
225 if (rep == NULL)
226 goto error_status;
227
228
229 if (rep->status) {
230 print_separator(stdout, params);
231
232 if (NO_JSON(params))
233 printf("General info:\n");
234
235 print_single_value(stdout, params, "Status", rep->status != 0 ? "online" : "error", 1);
236 print_single_value_int(stdout, params, "Server PID", rep->pid, 1);
237 print_single_value_int(stdout, params, "Sec-mod PID", rep->sec_mod_pids[0], 1);
238 print_single_value_int(stdout, params, "Sec-mod instance count", rep->n_sec_mod_pids, 1);
239
240 t = rep->start_time;
241 tm = localtime_r(&t, &_tm);
242 print_time_ival7(buf, time(0), t);
243 strftime(str_since, sizeof(str_since), DATE_TIME_FMT, tm);
244
245 print_single_value_ex(stdout, params, "Up since", str_since, buf, 1);
246 if (HAVE_JSON(params)) {
247 print_single_value_int(stdout, params, "raw_up_since", rep->start_time, 1);
248 print_single_value_int(stdout, params, "uptime", ((long)time(0)) - ((long)rep->start_time), 1);
249 }
250 print_single_value_int(stdout, params, "Active sessions", rep->active_clients, 1);
251 print_single_value_int(stdout, params, "Total sessions", rep->total_sessions_closed, 1);
252 print_single_value_int(stdout, params, "Total authentication failures", rep->total_auth_failures, 1);
253 print_single_value_int(stdout, params, "IPs in ban list", rep->banned_ips, 1);
254 if (params && params->debug) {
255 print_single_value_int(stdout, params, "Sec-mod client entries", rep->secmod_client_entries, 1);
256 #if defined(CAPTURE_LATENCY_SUPPORT)
257 print_single_value_int(stdout, params, "TLS DB entries", rep->stored_tls_sessions, 1);
258 #else
259 print_single_value_int(stdout, params, "TLS DB entries", rep->stored_tls_sessions, 0);
260 #endif
261 }
262
263 #if defined(CAPTURE_LATENCY_SUPPORT)
264 if (rep->has_latency_sample_count) {
265 unsigned int median_latency = (unsigned int)(rep->latency_sample_count ? rep->latency_median_total / rep->latency_sample_count : 0);
266 unsigned int stdev_latency = (unsigned int)(rep->latency_sample_count ? rep->latency_rms_total / rep->latency_sample_count : 0);
267
268 time2human(median_latency, buf, sizeof(buf));
269 print_single_value(stdout, params, "Median latency", buf, 1);
270 if (HAVE_JSON(params))
271 print_single_value_int(stdout, params, "raw_median_latency", median_latency, 1);
272
273 time2human(stdev_latency, buf, sizeof(buf));
274 print_single_value(stdout, params, "STDEV latency", buf, 1);
275 if (HAVE_JSON(params))
276 print_single_value_int(stdout, params, "raw_stdev_latency", stdev_latency, 1);
277
278 }
279 #endif
280
281 print_separator(stdout, params);
282 if (NO_JSON(params))
283 printf("Current stats period:\n");
284
285 t = rep->last_reset;
286 if (t > 0) {
287 tm = localtime_r(&t, &_tm);
288 print_time_ival7(buf, time(0), t);
289 strftime(str_since, sizeof(str_since), DATE_TIME_FMT, tm);
290
291 print_single_value_ex(stdout, params, "Last stats reset", str_since, buf, 1);
292 if (HAVE_JSON(params))
293 print_single_value_int(stdout, params, "raw_last_stats_reset", rep->last_reset, 1);
294 }
295
296 print_single_value_int(stdout, params, "Sessions handled", rep->sessions_closed, 1);
297 print_single_value_int(stdout, params, "Timed out sessions", rep->session_timeouts, 1);
298 print_single_value_int(stdout, params, "Timed out (idle) sessions", rep->session_idle_timeouts, 1);
299 print_single_value_int(stdout, params, "Closed due to error sessions", rep->session_errors, 1);
300 print_single_value_int(stdout, params, "Authentication failures", rep->auth_failures, 1);
301
302 print_time_ival7(buf, rep->avg_auth_time, 0);
303 print_single_value(stdout, params, "Average auth time", buf, 1);
304 if (HAVE_JSON(params))
305 print_single_value_int(stdout, params, "raw_avg_auth_time", rep->avg_auth_time, 1);
306
307 print_time_ival7(buf, rep->max_auth_time, 0);
308 print_single_value(stdout, params, "Max auth time", buf, 1);
309 if (HAVE_JSON(params))
310 print_single_value_int(stdout, params, "raw_max_auth_time", rep->max_auth_time, 1);
311
312 print_time_ival7(buf, rep->avg_session_mins*60, 0);
313 print_single_value(stdout, params, "Average session time", buf, 1);
314 if (HAVE_JSON(params))
315 print_single_value_int(stdout, params, "raw_avg_session_time", rep->avg_session_mins*60, 1);
316
317 print_time_ival7(buf, rep->max_session_mins*60, 0);
318 print_single_value(stdout, params, "Max session time", buf, 1);
319 if (HAVE_JSON(params))
320 print_single_value_int(stdout, params, "raw_max_session_time", rep->max_session_mins*60, 1);
321
322 if (rep->min_mtu > 0)
323 print_single_value_int(stdout, params, "Min MTU", rep->min_mtu, 1);
324 if (rep->max_mtu > 0)
325 print_single_value_int(stdout, params, "Max MTU", rep->max_mtu, 1);
326
327 bytes2human(rep->kbytes_in*1000, buf, sizeof(buf), "");
328 print_single_value(stdout, params, "RX", buf, 1);
329 if (HAVE_JSON(params))
330 print_single_value_int(stdout, params, "raw_rx", rep->kbytes_in*1000, 1);
331 bytes2human(rep->kbytes_out*1000, buf, sizeof(buf), "");
332 print_single_value(stdout, params, "TX", buf, 1);
333 if (HAVE_JSON(params))
334 print_single_value_int(stdout, params, "raw_tx", rep->kbytes_out*1000, 0);
335 }
336
337 print_end_block(stdout, params, 0);
338
339 status_rep__free_unpacked(rep, &pa);
340
341 ret = 0;
342 goto cleanup;
343
344 error_status:
345 print_single_value(stdout, params, "Status", "offline", 0);
346 print_end_block(stdout, params, 0);
347 ret = 1;
348
349 cleanup:
350 free_reply(&raw);
351 return ret;
352 }
353
handle_reload_cmd(struct unix_ctx * ctx,const char * arg,cmd_params_st * params)354 int handle_reload_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
355 {
356 int ret;
357 struct cmd_reply_st raw;
358 BoolMsg *rep;
359 unsigned status;
360 PROTOBUF_ALLOCATOR(pa, ctx);
361
362 init_reply(&raw);
363
364 ret = send_cmd(ctx, CTL_CMD_RELOAD, NULL, NULL, NULL, &raw);
365 if (ret < 0) {
366 goto error_status;
367 }
368
369 rep = bool_msg__unpack(&pa, raw.data_size, raw.data);
370 if (rep == NULL)
371 goto error_status;
372
373 status = rep->status;
374 bool_msg__free_unpacked(rep, &pa);
375
376 if (status != 0)
377 printf("Server scheduled to reload\n");
378 else
379 goto error_status;
380
381 ret = 0;
382 goto cleanup;
383
384 error_status:
385 printf("Error scheduling reload\n");
386 ret = 1;
387
388 cleanup:
389 free_reply(&raw);
390
391 return ret;
392 }
393
handle_stop_cmd(struct unix_ctx * ctx,const char * arg,cmd_params_st * params)394 int handle_stop_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
395 {
396 int ret;
397 struct cmd_reply_st raw;
398 BoolMsg *rep;
399 unsigned status;
400 PROTOBUF_ALLOCATOR(pa, ctx);
401
402 init_reply(&raw);
403
404 ret = send_cmd(ctx, CTL_CMD_STOP, NULL, NULL, NULL, &raw);
405 if (ret < 0) {
406 goto error_status;
407 }
408
409 rep = bool_msg__unpack(&pa, raw.data_size, raw.data);
410 if (rep == NULL)
411 goto error_status;
412
413 status = rep->status;
414 bool_msg__free_unpacked(rep, &pa);
415
416 if (status != 0)
417 printf("Server scheduled to stop\n");
418 else
419 goto error_status;
420
421 ret = 0;
422 goto cleanup;
423
424 error_status:
425 printf("Error scheduling server stop\n");
426 ret = 1;
427 goto cleanup;
428 cleanup:
429 free_reply(&raw);
430
431 return ret;
432 }
433
handle_unban_ip_cmd(struct unix_ctx * ctx,const char * arg,cmd_params_st * params)434 int handle_unban_ip_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
435 {
436 int ret;
437 struct cmd_reply_st raw;
438 BoolMsg *rep;
439 unsigned status;
440 UnbanReq req = UNBAN_REQ__INIT;
441 int af;
442 unsigned char tmp[16];
443 PROTOBUF_ALLOCATOR(pa, ctx);
444
445 if (arg == NULL || need_help(arg)) {
446 check_cmd_help(rl_line_buffer);
447 return 1;
448 }
449
450 init_reply(&raw);
451
452 /* convert the IP to the simplest form */
453 if (strchr(arg, ':') != 0) {
454 af = AF_INET6;
455 } else {
456 af = AF_INET;
457 }
458
459 ret = inet_pton(af, arg, tmp);
460 if (ret == 1) {
461 req.ip.data = tmp;
462 if (af == AF_INET)
463 req.ip.len = 4;
464 else
465 req.ip.len = 16;
466 } else {
467 fprintf(stderr, "Cannot parse IP: %s", arg);
468 return 1;
469 }
470
471 ret = send_cmd(ctx, CTL_CMD_UNBAN_IP, &req,
472 (pack_size_func)unban_req__get_packed_size,
473 (pack_func)unban_req__pack, &raw);
474 if (ret < 0) {
475 goto error;
476 }
477
478 rep = bool_msg__unpack(&pa, raw.data_size, raw.data);
479 if (rep == NULL)
480 goto error;
481
482 status = rep->status;
483 bool_msg__free_unpacked(rep, &pa);
484
485 if (status != 0) {
486 printf("IP '%s' was unbanned\n", arg);
487 ret = 0;
488 } else {
489 printf("could not unban IP '%s'\n", arg);
490 ret = 1;
491 }
492
493 goto cleanup;
494
495 error:
496 fprintf(stderr, ERR_SERVER_UNREACHABLE);
497 ret = 1;
498 cleanup:
499 free_reply(&raw);
500
501 return ret;
502 }
503
handle_disconnect_user_cmd(struct unix_ctx * ctx,const char * arg,cmd_params_st * params)504 int handle_disconnect_user_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
505 {
506 int ret;
507 struct cmd_reply_st raw;
508 BoolMsg *rep;
509 unsigned status;
510 UsernameReq req = USERNAME_REQ__INIT;
511 PROTOBUF_ALLOCATOR(pa, ctx);
512
513 if (arg == NULL || need_help(arg)) {
514 check_cmd_help(rl_line_buffer);
515 return 1;
516 }
517
518 init_reply(&raw);
519
520 req.username = (void*)arg;
521
522 ret = send_cmd(ctx, CTL_CMD_DISCONNECT_NAME, &req,
523 (pack_size_func)username_req__get_packed_size,
524 (pack_func)username_req__pack, &raw);
525 if (ret < 0) {
526 goto error;
527 }
528
529 rep = bool_msg__unpack(&pa, raw.data_size, raw.data);
530 if (rep == NULL)
531 goto error;
532
533 status = rep->status;
534 bool_msg__free_unpacked(rep, &pa);
535
536 if (status != 0) {
537 printf("user '%s' was disconnected\n", arg);
538 ret = 0;
539 } else {
540 printf("could not disconnect user '%s'\n", arg);
541 ret = 1;
542 }
543
544 goto cleanup;
545
546 error:
547 fprintf(stderr, ERR_SERVER_UNREACHABLE);
548 ret = 1;
549 cleanup:
550 free_reply(&raw);
551
552 return ret;
553 }
554
handle_disconnect_id_cmd(struct unix_ctx * ctx,const char * arg,cmd_params_st * params)555 int handle_disconnect_id_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
556 {
557 int ret;
558 struct cmd_reply_st raw;
559 BoolMsg *rep;
560 unsigned status;
561 unsigned id;
562 IdReq req = ID_REQ__INIT;
563 PROTOBUF_ALLOCATOR(pa, ctx);
564
565 if (arg != NULL)
566 id = atoi(arg);
567
568 if (arg == NULL || need_help(arg) || id == 0) {
569 check_cmd_help(rl_line_buffer);
570 return 1;
571 }
572
573 init_reply(&raw);
574
575 req.id = id;
576
577 ret = send_cmd(ctx, CTL_CMD_DISCONNECT_ID, &req,
578 (pack_size_func)id_req__get_packed_size,
579 (pack_func)id_req__pack, &raw);
580 if (ret < 0) {
581 goto error;
582 }
583
584 rep = bool_msg__unpack(&pa, raw.data_size, raw.data);
585 if (rep == NULL)
586 goto error;
587
588 status = rep->status;
589 bool_msg__free_unpacked(rep, &pa);
590
591 if (status != 0) {
592 printf("connection ID '%s' was disconnected\n", arg);
593 ret = 0;
594 } else {
595 printf("could not disconnect ID '%s'\n", arg);
596 ret = 1;
597 }
598
599 goto cleanup;
600
601 error:
602 fprintf(stderr, ERR_SERVER_UNREACHABLE);
603 ret = 1;
604 cleanup:
605 free_reply(&raw);
606
607 return ret;
608 }
609
fix_ciphersuite(char * txt)610 static const char *fix_ciphersuite(char *txt)
611 {
612 if (txt != NULL && txt[0] != 0) {
613 if (strlen(txt) > 16 && strncmp(txt, "(DTLS", 5) == 0 &&
614 (strncmp(&txt[8], ")-(RSA)-", 8) == 0 || strncmp(&txt[8], ")-(PSK)-", 8) == 0)) {
615 return txt + 16;
616 }
617 }
618
619 return "(no-dtls)";
620 }
621
get_ip(const char * ip1,const char * ip2)622 static const char *get_ip(const char *ip1, const char *ip2)
623 {
624 if (ip1 != NULL && ip1[0] != 0)
625 return ip1;
626 else
627 return ip2;
628 }
629
common_user_list(struct unix_ctx * ctx,UserListRep * rep,FILE * out,cmd_params_st * params)630 void common_user_list(struct unix_ctx *ctx, UserListRep *rep, FILE *out, cmd_params_st *params)
631 {
632 unsigned i;
633 const char *vpn_ip, *username;
634 const char *dtls_ciphersuite;
635 char tmpbuf[MAX_TMPSTR_SIZE];
636 time_t t;
637 struct tm *tm, _tm;
638 char str_since[64];
639
640 if (HAVE_JSON(params)) {
641 common_info_cmd(rep, out, params);
642 } else for (i=0;i<rep->n_user;i++) {
643 username = rep->user[i]->username;
644 if (username == NULL || username[0] == 0)
645 username = NO_USER;
646
647 vpn_ip = get_ip(rep->user[i]->local_ip, rep->user[i]->local_ip6);
648
649 /* add header */
650 if (i == 0) {
651 fprintf(out, "%8s %8s %8s %14s %14s %6s %7s %14s %9s\n",
652 "id", "user", "vhost", "ip", "vpn-ip", "device",
653 "since", "dtls-cipher", "status");
654 }
655
656 t = rep->user[i]->conn_time;
657 tm = localtime_r(&t, &_tm);
658 strftime(str_since, sizeof(str_since), DATE_TIME_FMT, tm);
659
660 print_time_ival7(tmpbuf, time(0), t);
661
662 fprintf(out, "%8d %8s %8s %14s %14s %6s ",
663 (int)rep->user[i]->id, username, rep->user[i]->vhost, rep->user[i]->ip, vpn_ip, rep->user[i]->tun);
664
665 dtls_ciphersuite = fix_ciphersuite(rep->user[i]->dtls_ciphersuite);
666
667 fprintf(out, "%s %14s %9s\n", tmpbuf, dtls_ciphersuite, ps_status_to_str(rep->user[i]->status, 0));
668
669 entries_add(ctx, username, strlen(username), rep->user[i]->id);
670 }
671 }
672
handle_list_users_cmd(struct unix_ctx * ctx,const char * arg,cmd_params_st * params)673 int handle_list_users_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
674 {
675 int ret;
676 struct cmd_reply_st raw;
677 UserListRep *rep = NULL;
678 FILE *out;
679 PROTOBUF_ALLOCATOR(pa, ctx);
680
681 init_reply(&raw);
682
683 entries_clear();
684
685 out = pager_start(params);
686
687 ret = send_cmd(ctx, CTL_CMD_LIST, NULL, NULL, NULL, &raw);
688 if (ret < 0) {
689 goto error;
690 }
691
692 rep = user_list_rep__unpack(&pa, raw.data_size, raw.data);
693 if (rep == NULL)
694 goto error;
695
696 common_user_list(ctx, rep, out, params);
697
698 ret = 0;
699 goto cleanup;
700
701 error:
702 ret = 1;
703 fprintf(stderr, ERR_SERVER_UNREACHABLE);
704
705 cleanup:
706 if (rep != NULL)
707 user_list_rep__free_unpacked(rep, &pa);
708
709 free_reply(&raw);
710 pager_stop(out);
711
712 return ret;
713 }
714
shorten(void * cookie,unsigned session_id_size,unsigned small)715 static char *shorten(void *cookie, unsigned session_id_size, unsigned small)
716 {
717 static char psid[SAFE_ID_SIZE];
718
719 assert(session_id_size <= SAFE_ID_SIZE);
720 memcpy(psid, cookie, session_id_size);
721
722 if (small)
723 psid[6] = 0;
724 else
725 psid[SAFE_ID_SIZE-1] = 0;
726
727 return psid;
728 }
729
730 static
session_list(struct unix_ctx * ctx,SecmListCookiesReplyMsg * rep,FILE * out,cmd_params_st * params,unsigned all)731 void session_list(struct unix_ctx *ctx, SecmListCookiesReplyMsg *rep, FILE *out, cmd_params_st *params,
732 unsigned all)
733 {
734 unsigned i;
735 const char *username;
736 char tmpbuf[MAX_TMPSTR_SIZE] = "";
737 time_t t;
738 struct tm *tm, _tm;
739 char str_since[65];
740 const char *sid;
741
742 session_entries_clear();
743
744 if (HAVE_JSON(params)) {
745 session_info_cmd(ctx, rep, out, params, NULL, all);
746 } else for (i=0;i<rep->n_cookies;i++) {
747 if (!all && rep->cookies[i]->status != PS_AUTH_COMPLETED)
748 continue;
749
750 username = rep->cookies[i]->username;
751 if (username == NULL || username[0] == 0)
752 username = NO_USER;
753
754 /* add header */
755 if (i == 0) {
756 fprintf(out, "%6s %8s %8s %14s %24s %8s %8s\n",
757 "session", "user", "vhost", "ip", "user agent", "created", "status");
758 }
759
760 t = rep->cookies[i]->created;
761 if (t > 0) {
762 tm = localtime_r(&t, &_tm);
763 strftime(str_since, sizeof(str_since), DATE_TIME_FMT, tm);
764 print_time_ival7(tmpbuf, time(0), t);
765 }
766
767 sid = shorten(rep->cookies[i]->safe_id.data, rep->cookies[i]->safe_id.len, 1);
768 session_entries_add(ctx, sid);
769
770 fprintf(out, "%.6s %8s %8s %14s %.24s %8s %8s\n",
771 sid, username, rep->cookies[i]->vhost, rep->cookies[i]->remote_ip,
772 rep->cookies[i]->user_agent, tmpbuf, ps_status_to_str(rep->cookies[i]->status, 1));
773 }
774 }
775
776 static
handle_list_sessions_cmd(struct unix_ctx * ctx,const char * arg,cmd_params_st * params,unsigned all)777 int handle_list_sessions_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params, unsigned all)
778 {
779 int ret;
780 struct cmd_reply_st raw;
781 SecmListCookiesReplyMsg *rep = NULL;
782 FILE *out;
783 PROTOBUF_ALLOCATOR(pa, ctx);
784
785 init_reply(&raw);
786
787 entries_clear();
788
789 out = pager_start(params);
790
791 ret = send_cmd(ctx, CTL_CMD_LIST_COOKIES, NULL, NULL, NULL, &raw);
792 if (ret < 0) {
793 goto error;
794 }
795
796 rep = secm_list_cookies_reply_msg__unpack(&pa, raw.data_size, raw.data);
797 if (rep == NULL)
798 goto error;
799
800 session_list(ctx, rep, out, params, all);
801
802 ret = 0;
803 goto cleanup;
804
805 error:
806 ret = 1;
807 fprintf(stderr, ERR_SERVER_UNREACHABLE);
808
809 cleanup:
810 if (rep != NULL)
811 secm_list_cookies_reply_msg__free_unpacked(rep, &pa);
812
813 free_reply(&raw);
814 pager_stop(out);
815
816 return ret;
817 }
818
handle_show_session_cmd(struct unix_ctx * ctx,const char * arg,cmd_params_st * params)819 int handle_show_session_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
820 {
821 int ret;
822 struct cmd_reply_st raw;
823 SecmListCookiesReplyMsg *rep = NULL;
824 FILE *out;
825 const char *sid = (void*)arg;
826 PROTOBUF_ALLOCATOR(pa, ctx);
827
828 if (arg == NULL || need_help(arg)) {
829 check_cmd_help(rl_line_buffer);
830 return 1;
831 }
832
833 init_reply(&raw);
834
835 entries_clear();
836
837 out = pager_start(params);
838
839 ret = send_cmd(ctx, CTL_CMD_LIST_COOKIES, NULL, NULL, NULL, &raw);
840 if (ret < 0) {
841 goto error;
842 }
843
844 rep = secm_list_cookies_reply_msg__unpack(&pa, raw.data_size, raw.data);
845 if (rep == NULL)
846 goto error;
847
848 session_info_cmd(ctx, rep, out, params, sid, 0);
849
850 ret = 0;
851 goto cleanup;
852
853 error:
854 ret = 1;
855 fprintf(stderr, ERR_SERVER_UNREACHABLE);
856
857 cleanup:
858 if (rep != NULL)
859 secm_list_cookies_reply_msg__free_unpacked(rep, &pa);
860
861 free_reply(&raw);
862 pager_stop(out);
863
864 return ret;
865 }
866
handle_list_valid_sessions_cmd(struct unix_ctx * ctx,const char * arg,cmd_params_st * params)867 int handle_list_valid_sessions_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
868 {
869 return handle_list_sessions_cmd(ctx, arg, params, 0);
870 }
871
handle_list_all_sessions_cmd(struct unix_ctx * ctx,const char * arg,cmd_params_st * params)872 int handle_list_all_sessions_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
873 {
874 return handle_list_sessions_cmd(ctx, arg, params, 1);
875 }
876
handle_list_iroutes_cmd(struct unix_ctx * ctx,const char * arg,cmd_params_st * params)877 int handle_list_iroutes_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
878 {
879 int ret;
880 struct cmd_reply_st raw;
881 UserListRep *rep = NULL;
882 FILE *out;
883 unsigned i, j;
884 PROTOBUF_ALLOCATOR(pa, ctx);
885
886 init_reply(&raw);
887
888 entries_clear();
889
890 out = pager_start(params);
891
892 /* get all user info */
893 ret = send_cmd(ctx, CTL_CMD_LIST, NULL, NULL, NULL, &raw);
894 if (ret < 0) {
895 goto error;
896 }
897
898 rep = user_list_rep__unpack(&pa, raw.data_size, raw.data);
899 if (rep == NULL)
900 goto error;
901
902 /* print iroutes */
903 if (NO_JSON(params)) {
904 for (i=0;i<rep->n_user;i++) {
905 const char *username, *vpn_ip;
906
907 username = rep->user[i]->username;
908 if (username == NULL || username[0] == 0)
909 username = NO_USER;
910
911 vpn_ip = get_ip(rep->user[i]->local_ip, rep->user[i]->local_ip6);
912
913 /* add header */
914 if (i == 0) {
915 fprintf(out, "%6s %8s %8s %6s %16s %28s\n",
916 "id", "user", "vhost", "device", "vpn-ip", "iroute");
917 }
918
919 for (j=0;j<rep->user[i]->n_iroutes;j++)
920 fprintf(out, "%6d %8s %8s %6s %16s %28s\n",
921 (int)rep->user[i]->id, username, rep->user[i]->vhost, rep->user[i]->tun, vpn_ip, rep->user[i]->iroutes[j]);
922
923 }
924 } else {
925 print_start_block(out, params);
926 for (i=0;i<rep->n_user;i++) {
927 const char *username, *vpn_ip;
928
929 username = rep->user[i]->username;
930 if (username == NULL || username[0] == 0)
931 username = NO_USER;
932
933 vpn_ip = get_ip(rep->user[i]->local_ip, rep->user[i]->local_ip6);
934
935 print_single_value_int(out, params, "ID", rep->user[i]->id, 1);
936 print_single_value(out, params, "Username", username, 1);
937 print_single_value(out, params, "vhost", rep->user[i]->vhost, 1);
938 print_single_value(out, params, "Device", rep->user[i]->tun, 1);
939 print_single_value(out, params, "IP", vpn_ip, 1);
940 print_list_entries(out, params, "iRoutes", rep->user[i]->iroutes, rep->user[i]->n_iroutes, 1);
941 print_single_value(out, params, "IP", vpn_ip, 0);
942 }
943 print_end_block(out, params, 0);
944 }
945
946 ret = 0;
947 goto cleanup;
948
949 error:
950 ret = 1;
951 fprintf(stderr, ERR_SERVER_UNREACHABLE);
952
953 cleanup:
954 if (rep != NULL)
955 user_list_rep__free_unpacked(rep, &pa);
956
957 free_reply(&raw);
958 pager_stop(out);
959
960 return ret;
961 }
962
963 static
handle_list_banned_cmd(struct unix_ctx * ctx,const char * arg,cmd_params_st * params,unsigned points)964 int handle_list_banned_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params, unsigned points)
965 {
966 int ret;
967 struct cmd_reply_st raw;
968 BanListRep *rep = NULL;
969 unsigned i;
970 char str_since[64];
971 char tmpbuf[MAX_TMPSTR_SIZE];
972 FILE *out;
973 struct tm *tm, _tm;
974 time_t t;
975 PROTOBUF_ALLOCATOR(pa, ctx);
976 char txt_ip[MAX_IP_STR];
977 const char *tmp_str;
978
979 init_reply(&raw);
980
981 ip_entries_clear();
982
983 out = pager_start(params);
984
985 ret = send_cmd(ctx, CTL_CMD_LIST_BANNED, NULL, NULL, NULL, &raw);
986 if (ret < 0) {
987 goto error;
988 }
989
990 rep = ban_list_rep__unpack(&pa, raw.data_size, raw.data);
991 if (rep == NULL)
992 goto error;
993
994 print_array_block(out, params);
995
996 for (i=0;i<rep->n_info;i++) {
997 if (rep->info[i]->ip.len < 4)
998 continue;
999
1000 if (rep->info[i]->ip.len == 16)
1001 tmp_str = inet_ntop(AF_INET6, rep->info[i]->ip.data, txt_ip, sizeof(txt_ip));
1002 else
1003 tmp_str = inet_ntop(AF_INET, rep->info[i]->ip.data, txt_ip, sizeof(txt_ip));
1004 if (tmp_str == NULL)
1005 strlcpy(txt_ip, "(unknown)", sizeof(txt_ip));
1006
1007 /* add header */
1008 if (points == 0) {
1009 if (rep->info[i]->has_expires) {
1010 t = rep->info[i]->expires;
1011 tm = localtime_r(&t, &_tm);
1012 strftime(str_since, sizeof(str_since), DATE_TIME_FMT, tm);
1013 } else {
1014 continue;
1015 }
1016
1017 if (i == 0 && NO_JSON(params)) {
1018 fprintf(out, "%14s %14s %30s\n",
1019 "IP", "score", "expires");
1020 }
1021 print_start_block(out, params);
1022
1023 print_time_ival7(tmpbuf, t, time(0));
1024
1025 if (HAVE_JSON(params)) {
1026 print_single_value(out, params, "IP", txt_ip, 1);
1027 print_single_value_ex(out, params, "Since", str_since, tmpbuf, 1);
1028 print_single_value_int(out, params, "Score", rep->info[i]->score, 0);
1029 } else {
1030 fprintf(out, "%14s %14u %30s (%s)\n",
1031 txt_ip, (unsigned)rep->info[i]->score, str_since, tmpbuf);
1032 }
1033 } else {
1034 if (i == 0 && NO_JSON(params)) {
1035 fprintf(out, "%14s %14s\n",
1036 "IP", "score");
1037 }
1038 print_start_block(out, params);
1039
1040 if (HAVE_JSON(params)) {
1041 print_single_value(out, params, "IP", txt_ip, 1);
1042 print_single_value_int(out, params, "Score", rep->info[i]->score, 0);
1043 } else {
1044 fprintf(out, "%14s %14u\n",
1045 txt_ip, (unsigned)rep->info[i]->score);
1046 }
1047 }
1048
1049 print_end_block(out, params, i<(rep->n_info-1)?1:0);
1050
1051 ip_entries_add(ctx, txt_ip, strlen(txt_ip));
1052 }
1053
1054 print_end_array_block(out, params);
1055
1056 ret = 0;
1057 goto cleanup;
1058
1059 error:
1060 ret = 1;
1061 fprintf(stderr, ERR_SERVER_UNREACHABLE);
1062
1063 cleanup:
1064 if (rep != NULL)
1065 ban_list_rep__free_unpacked(rep, &pa);
1066
1067 free_reply(&raw);
1068 pager_stop(out);
1069
1070 return ret;
1071 }
1072
handle_list_banned_ips_cmd(struct unix_ctx * ctx,const char * arg,cmd_params_st * params)1073 int handle_list_banned_ips_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
1074 {
1075 return handle_list_banned_cmd(ctx, arg, params, 0);
1076 }
1077
handle_list_banned_points_cmd(struct unix_ctx * ctx,const char * arg,cmd_params_st * params)1078 int handle_list_banned_points_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
1079 {
1080 return handle_list_banned_cmd(ctx, arg, params, 1);
1081 }
1082
1083
int2str(char tmpbuf[MAX_TMPSTR_SIZE],int i)1084 static char *int2str(char tmpbuf[MAX_TMPSTR_SIZE], int i)
1085 {
1086 tmpbuf[0] = 0;
1087 snprintf(tmpbuf, MAX_TMPSTR_SIZE, "%d", i);
1088 return tmpbuf;
1089 }
1090
1091 static
common_info_cmd(UserListRep * args,FILE * out,cmd_params_st * params)1092 int common_info_cmd(UserListRep * args, FILE *out, cmd_params_st *params)
1093 {
1094 char *username = "";
1095 char *groupname = "";
1096 char str_since[64];
1097 char tmpbuf[MAX_TMPSTR_SIZE];
1098 char tmpbuf2[MAX_TMPSTR_SIZE];
1099 struct tm *tm, _tm;
1100 time_t t;
1101 unsigned at_least_one = 0;
1102 int ret = 1, r;
1103 unsigned i;
1104 unsigned init_pager = 0;
1105
1106 if (out == NULL) {
1107 out = pager_start(params);
1108 init_pager = 1;
1109 }
1110
1111 if (HAVE_JSON(params))
1112 fprintf(out, "[\n");
1113
1114 for (i=0;i<args->n_user;i++) {
1115 if (at_least_one > 0)
1116 fprintf(out, "\n");
1117
1118 print_start_block(out, params);
1119
1120 print_single_value_int(out, params, "ID", args->user[i]->id, 1);
1121
1122 t = args->user[i]->conn_time;
1123 tm = localtime_r(&t, &_tm);
1124 strftime(str_since, sizeof(str_since), DATE_TIME_FMT, tm);
1125
1126 username = args->user[i]->username;
1127 if (username == NULL || username[0] == 0)
1128 username = NO_USER;
1129
1130
1131 groupname = args->user[i]->groupname;
1132 if (groupname == NULL || groupname[0] == 0)
1133 groupname = NO_GROUP;
1134
1135 print_pair_value(out, params, "Username", username, "Groupname", groupname, 1);
1136
1137 print_single_value(out, params, "State", ps_status_to_str(args->user[i]->status, 0), 1);
1138 print_single_value(out, params, "vhost", args->user[i]->vhost, 1);
1139 if (args->user[i]->has_mtu != 0)
1140 print_pair_value(out, params, "Device", args->user[i]->tun, "MTU", int2str(tmpbuf, args->user[i]->mtu), 1);
1141 else
1142 print_single_value(out, params, "Device", args->user[i]->tun, 1);
1143 print_pair_value(out, params, "Remote IP", args->user[i]->ip, "Location", geo_lookup(args->user[i]->ip, tmpbuf, sizeof(tmpbuf)), 1);
1144 print_single_value(out, params, "Local Device IP", args->user[i]->local_dev_ip, 1);
1145
1146 if (args->user[i]->local_ip != NULL && args->user[i]->local_ip[0] != 0 &&
1147 args->user[i]->remote_ip != NULL && args->user[i]->remote_ip[0] != 0) {
1148 print_pair_value(out, params, "IPv4", args->user[i]->local_ip, "P-t-P IPv4", args->user[i]->remote_ip, 1);
1149 }
1150 if (args->user[i]->local_ip6 != NULL && args->user[i]->local_ip6[0] != 0 &&
1151 args->user[i]->remote_ip6 != NULL && args->user[i]->remote_ip6[0] != 0) {
1152 print_pair_value(out, params, "IPv6", args->user[i]->local_ip6, "P-t-P IPv6", args->user[i]->remote_ip6, 1);
1153 }
1154
1155 print_single_value(out, params, "User-Agent", args->user[i]->user_agent, 1);
1156
1157 if (args->user[i]->rx_per_sec > 0 || args->user[i]->tx_per_sec > 0) {
1158 /* print limits */
1159 char buf1[32];
1160 char buf2[32];
1161
1162 if (args->user[i]->rx_per_sec > 0 && args->user[i]->tx_per_sec > 0) {
1163 bytes2human(args->user[i]->rx_per_sec, buf1, sizeof(buf1), "/sec");
1164 bytes2human(args->user[i]->tx_per_sec, buf2, sizeof(buf2), "/sec");
1165
1166 print_pair_value(out, params, "Limit RX", buf1, "TX", buf2, 1);
1167 } else if (args->user[i]->tx_per_sec > 0) {
1168 bytes2human(args->user[i]->tx_per_sec, buf1, sizeof(buf1), "/sec");
1169 print_single_value(out, params, "Limit TX", buf1, 1);
1170 } else if (args->user[i]->rx_per_sec > 0) {
1171 bytes2human(args->user[i]->rx_per_sec, buf1, sizeof(buf1), "/sec");
1172 print_single_value(out, params, "Limit RX", buf1, 1);
1173 }
1174 }
1175
1176 print_iface_stats(args->user[i]->tun, args->user[i]->conn_time, out, params, 1);
1177
1178 print_pair_value(out, params, "DPD", int2str(tmpbuf, args->user[i]->dpd), "KeepAlive", int2str(tmpbuf2, args->user[i]->keepalive), 1);
1179
1180 print_single_value(out, params, "Hostname", args->user[i]->hostname, 1);
1181
1182 print_time_ival7(tmpbuf, time(0), t);
1183 print_single_value_ex(out, params, "Connected at", str_since, tmpbuf, 1);
1184
1185 if (HAVE_JSON(params)) {
1186 print_single_value(out, params, "Full session", shorten(args->user[i]->safe_id.data, args->user[i]->safe_id.len, 0), 1);
1187 #ifdef OCSERV_0_11_6_COMPAT
1188 /* compat with previous versions */
1189 print_single_value(out, params, "Raw cookie", shorten(args->user[i]->safe_id.data, args->user[i]->safe_id.len, 0), 1);
1190 print_single_value(out, params, "Cookie", shorten(args->user[i]->safe_id.data, args->user[i]->safe_id.len, 1), 1);
1191 #endif
1192 }
1193 print_single_value(out, params, "Session", shorten(args->user[i]->safe_id.data, args->user[i]->safe_id.len, 1), 1);
1194
1195 print_single_value(out, params, "TLS ciphersuite", args->user[i]->tls_ciphersuite, 1);
1196 print_single_value(out, params, "DTLS cipher", args->user[i]->dtls_ciphersuite, 1);
1197 print_pair_value(out, params, "CSTP compression", args->user[i]->cstp_compr, "DTLS compression", args->user[i]->dtls_compr, 1);
1198
1199 print_separator(out, params);
1200 /* user network info */
1201 if (print_list_entries(out, params, "DNS", args->user[i]->dns, args->user[i]->n_dns, 1) < 0)
1202 goto error_parse;
1203
1204 if (print_list_entries(out, params, "NBNS", args->user[i]->nbns, args->user[i]->n_nbns, 1) < 0)
1205 goto error_parse;
1206
1207 if (print_list_entries(out, params, "Split-DNS-Domains", args->user[i]->domains, args->user[i]->n_domains, 1) < 0)
1208 goto error_parse;
1209
1210 if ((r = print_list_entries(out, params, "Routes", args->user[i]->routes, args->user[i]->n_routes, 1)) < 0)
1211 goto error_parse;
1212 if (r == 0) {
1213 print_single_value(out, params, "Routes", "defaultroute", 1);
1214 }
1215
1216 if (print_list_entries(out, params, "No-routes", args->user[i]->no_routes, args->user[i]->n_no_routes, 1) < 0)
1217 goto error_parse;
1218
1219 if (print_list_entries(out, params, "iRoutes", args->user[i]->iroutes, args->user[i]->n_iroutes, 1) < 0)
1220 goto error_parse;
1221
1222 print_single_value(out, params, "Restricted to routes", args->user[i]->restrict_to_routes?"True":"False", 1);
1223
1224 if (print_fwport_entries(out, params, "Restricted to ports", args->user[i]->fw_ports, args->user[i]->n_fw_ports, 0) < 0)
1225 goto error_parse;
1226
1227 print_end_block(out, params, i<(args->n_user-1)?1:0);
1228
1229 at_least_one = 1;
1230 }
1231
1232 if (HAVE_JSON(params))
1233 fprintf(out, "]\n");
1234
1235 ret = 0;
1236 goto cleanup;
1237
1238 error_parse:
1239 fprintf(stderr, "%s: message parsing error\n", __func__);
1240 goto cleanup;
1241 cleanup:
1242 if (at_least_one == 0) {
1243 if (NO_JSON(params))
1244 fprintf(out, "user or ID not found\n");
1245 ret = 2;
1246 }
1247 if (init_pager)
1248 pager_stop(out);
1249
1250 return ret;
1251 }
1252
1253 static
session_info_cmd(void * ctx,SecmListCookiesReplyMsg * args,FILE * out,cmd_params_st * params,const char * lsid,unsigned all)1254 int session_info_cmd(void *ctx, SecmListCookiesReplyMsg * args, FILE *out,
1255 cmd_params_st *params, const char *lsid, unsigned all)
1256 {
1257 const char *username, *groupname;
1258 char str_since[65];
1259 char str_since2[65];
1260 struct tm *tm, _tm;
1261 time_t t;
1262 unsigned at_least_one = 0;
1263 int ret = 1;
1264 unsigned i;
1265 const char *sid;
1266 unsigned init_pager = 0;
1267 unsigned int match_len = 0;
1268 char tmpbuf[MAX_TMPSTR_SIZE];
1269
1270 if (lsid)
1271 match_len = strlen(lsid);
1272
1273 if (out == NULL) {
1274 out = pager_start(params);
1275 init_pager = 1;
1276 }
1277
1278 if (HAVE_JSON(params))
1279 fprintf(out, "[\n");
1280
1281 session_entries_clear();
1282
1283 for (i=0;i<args->n_cookies;i++) {
1284 if (!all && args->cookies[i]->status != PS_AUTH_COMPLETED && lsid == NULL)
1285 continue;
1286
1287 sid = shorten(args->cookies[i]->safe_id.data, args->cookies[i]->safe_id.len, 1);
1288 session_entries_add(ctx, sid);
1289
1290 if (lsid && strncmp(sid, lsid, match_len) != 0)
1291 continue;
1292
1293 if (at_least_one > 0)
1294 fprintf(out, "\n");
1295
1296 print_start_block(out, params);
1297
1298 print_single_value(out, params, "Session", sid, 1);
1299 if (HAVE_JSON(params))
1300 print_single_value(out, params, "Full session", shorten(args->cookies[i]->safe_id.data, args->cookies[i]->safe_id.len, 0), 1);
1301 else
1302 print_single_value(out, params, "Full session ID", shorten(args->cookies[i]->safe_id.data, args->cookies[i]->safe_id.len, 0), 1);
1303
1304 t = args->cookies[i]->created;
1305
1306 str_since[0] = 0;
1307 str_since2[0] = 0;
1308
1309 if (t > 0) {
1310 tm = localtime_r(&t, &_tm);
1311 strftime(str_since, sizeof(str_since), DATE_TIME_FMT, tm);
1312 }
1313
1314 t = args->cookies[i]->expires;
1315
1316 if (t > 0) {
1317 tm = localtime_r(&t, &_tm);
1318 strftime(str_since2, sizeof(str_since2), DATE_TIME_FMT, tm);
1319 }
1320 print_pair_value(out, params, "Created", str_since, "Expires", str_since2, 1);
1321
1322 print_single_value(out, params, "State", ps_status_to_str(args->cookies[i]->status, 1), 1);
1323
1324 username = args->cookies[i]->username;
1325 if (username == NULL || username[0] == 0)
1326 username = NO_USER;
1327
1328 groupname = args->cookies[i]->groupname;
1329 if (groupname == NULL || groupname[0] == 0)
1330 groupname = NO_GROUP;
1331
1332 print_pair_value(out, params, "Username", username, "Groupname", groupname, 1);
1333 print_pair_value(out, params, "vhost", args->cookies[i]->vhost, "User-Agent", args->cookies[i]->user_agent, 1);
1334 print_pair_value(out, params, "Remote IP", args->cookies[i]->remote_ip, "Location", geo_lookup(args->cookies[i]->remote_ip, tmpbuf, sizeof(tmpbuf)), 1);
1335
1336 if (HAVE_JSON(params)) {
1337 /* old names for compatibility */
1338 print_single_value_int(out, params, "session_is_open", args->cookies[i]->session_is_open, 1);
1339 print_single_value_int(out, params, "tls_auth_ok", args->cookies[i]->tls_auth_ok, 1);
1340 print_single_value_int(out, params, "in_use", args->cookies[i]->in_use, 1);
1341 } else {
1342 /* old names for compatibility */
1343 print_pair_value(out, params, "In use", args->cookies[i]->in_use?"True":"False",
1344 "Activated", args->cookies[i]->session_is_open?"True":"False", 1);
1345 print_single_value(out, params, "Certificate auth", args->cookies[i]->tls_auth_ok?"True":"False", 1);
1346 }
1347
1348 #ifdef OCSERV_0_11_6_COMPAT
1349 if (HAVE_JSON(params)) {
1350 /* compat with previous versions */
1351 print_single_value(out, params, "Last Modified", str_since, 1);
1352 print_single_value(out, params, "Raw cookie", shorten(args->cookies[i]->safe_id.data, args->cookies[i]->safe_id.len, 0), 1);
1353 print_single_value(out, params, "Cookie", shorten(args->cookies[i]->safe_id.data, args->cookies[i]->safe_id.len, 1), 1);
1354 }
1355 #endif
1356
1357 print_end_block(out, params, i<(args->n_cookies-1)?1:0);
1358
1359 at_least_one = 1;
1360 }
1361
1362 if (HAVE_JSON(params))
1363 fprintf(out, "]\n");
1364
1365 ret = 0;
1366 goto cleanup;
1367
1368 cleanup:
1369 if (at_least_one == 0) {
1370 if (NO_JSON(params))
1371 fprintf(out, "Session ID not found or expired\n");
1372 ret = 2;
1373 }
1374 if (init_pager)
1375 pager_stop(out);
1376
1377 return ret;
1378 }
1379
handle_show_user_cmd(struct unix_ctx * ctx,const char * arg,cmd_params_st * params)1380 int handle_show_user_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
1381 {
1382 int ret;
1383 struct cmd_reply_st raw;
1384 UserListRep *rep = NULL;
1385 UsernameReq req = USERNAME_REQ__INIT;
1386 PROTOBUF_ALLOCATOR(pa, ctx);
1387
1388 if (arg == NULL || need_help(arg)) {
1389 check_cmd_help(rl_line_buffer);
1390 return 1;
1391 }
1392
1393 init_reply(&raw);
1394
1395 req.username = (void*)arg;
1396
1397 ret = send_cmd(ctx, CTL_CMD_USER_INFO, &req,
1398 (pack_size_func)username_req__get_packed_size,
1399 (pack_func)username_req__pack, &raw);
1400 if (ret < 0) {
1401 goto error;
1402 }
1403
1404 rep = user_list_rep__unpack(&pa, raw.data_size, raw.data);
1405 if (rep == NULL)
1406 goto error;
1407
1408 ret = common_info_cmd(rep, NULL, params);
1409 if (ret < 0)
1410 goto error;
1411
1412
1413
1414 goto cleanup;
1415
1416 error:
1417 fprintf(stderr, ERR_SERVER_UNREACHABLE);
1418 ret = 1;
1419 cleanup:
1420 if (rep != NULL)
1421 user_list_rep__free_unpacked(rep, &pa);
1422 free_reply(&raw);
1423
1424 return ret;
1425 }
1426
dummy_sighandler(int signo)1427 static void dummy_sighandler(int signo)
1428 {
1429 return;
1430 }
1431
1432
handle_events_cmd(struct unix_ctx * ctx,const char * arg,cmd_params_st * params)1433 int handle_events_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
1434 {
1435 uint8_t header[5];
1436 int ret;
1437 struct cmd_reply_st raw;
1438 UserListRep *rep1 = NULL;
1439 TopUpdateRep *rep2 = NULL;
1440 uint32_t slength;
1441 unsigned data_size;
1442 uint8_t *data = NULL;
1443 char tmpbuf[MAX_TMPSTR_SIZE];
1444 PROTOBUF_ALLOCATOR(pa, ctx);
1445 struct termios tio_old, tio_new;
1446 SIGHANDLER_T old_sighandler;
1447 fd_set rfds;
1448
1449 init_reply(&raw);
1450
1451 ret = send_cmd(ctx, CTL_CMD_TOP, NULL, 0, 0, &raw);
1452 if (ret < 0) {
1453 goto error;
1454 }
1455
1456 rep1 = user_list_rep__unpack(&pa, raw.data_size, raw.data);
1457 if (rep1 == NULL)
1458 goto error;
1459
1460 common_user_list(ctx, rep1, stdout, params);
1461
1462 user_list_rep__free_unpacked(rep1, &pa);
1463 rep1 = NULL;
1464
1465 fputs("\n", stdout);
1466 fputs("Press 'q' or CTRL+C to quit\n\n", stdout);
1467
1468 old_sighandler = ocsignal(SIGINT, dummy_sighandler);
1469 tcgetattr(STDIN_FILENO, &tio_old);
1470 tio_new = tio_old;
1471 tio_new.c_lflag &= ~(ICANON|ECHO);
1472 tcsetattr(STDIN_FILENO, TCSANOW, &tio_new);
1473
1474 /* start listening for updates */
1475 while(1) {
1476 FD_ZERO(&rfds);
1477 #ifndef __clang_analyzer__
1478 /* for some reason this confuses the clang static analyzer */
1479 FD_SET(STDIN_FILENO, &rfds);
1480 #endif
1481 FD_SET(ctx->fd, &rfds);
1482
1483 ret = select(MAX(STDIN_FILENO,ctx->fd)+1, &rfds, NULL, NULL, NULL);
1484 if (ret == -1 && errno == EINTR) {
1485 ret = 0;
1486 break;
1487 }
1488
1489 if (ret == -1) {
1490 int e = errno;
1491 fprintf(stderr, "events: select: %s\n", strerror(e));
1492 ret = -1;
1493 break;
1494 }
1495
1496 if (FD_ISSET(STDIN_FILENO, &rfds)) {
1497 ret = getchar();
1498 if (ret == 'q' || ret == 'Q') {
1499 ret = 0;
1500 break;
1501 }
1502 }
1503
1504 if (!FD_ISSET(ctx->fd, &rfds))
1505 continue;
1506
1507 assert(sizeof(header) == 1+sizeof(slength));
1508 ret = force_read_timeout(ctx->fd, header, 1+sizeof(slength), DEFAULT_TIMEOUT);
1509 if (ret == -1) {
1510 int e = errno;
1511 fprintf(stderr, "events: read1: %s\n", strerror(e));
1512 ret = -1;
1513 break;
1514 }
1515
1516 if (ret == 0) {
1517 fprintf(stderr, "events: server closed the connection\n");
1518 ret = 0;
1519 break;
1520 }
1521
1522 if (ret != 1+sizeof(slength)) {
1523 fprintf(stderr, "events: short read %d\n", ret);
1524 ret = -1;
1525 break;
1526 }
1527
1528 if (header[0] != CTL_CMD_TOP_UPDATE_REP) {
1529 fprintf(stderr, "events: Unexpected message '%d', expected '%d'\n", (int)header[0], (int)CTL_CMD_TOP_UPDATE_REP);
1530 ret = -1;
1531 break;
1532 }
1533
1534 memcpy(&slength, &header[1], sizeof(slength));
1535
1536 data_size = slength;
1537 data = talloc_size(ctx, slength);
1538 if (data == NULL) {
1539 fprintf(stderr, "events: memory error\n");
1540 ret = -1;
1541 break;
1542 }
1543
1544 ret = force_read(ctx->fd, data, data_size);
1545 if (ret == -1) {
1546 int e = errno;
1547 fprintf(stderr, "events: read: %s\n", strerror(e));
1548 ret = -1;
1549 break;
1550 }
1551
1552 /* parse and print */
1553 rep2 = top_update_rep__unpack(&pa, data_size, data);
1554 if (rep2 == NULL)
1555 goto error;
1556
1557 if (HAVE_JSON(params)) {
1558 common_info_cmd(rep2->user, stdout, params);
1559 } else {
1560 if (rep2->connected) {
1561 printf("%s: connected user '%s' (%u) from %s with IP %s\n",
1562 rep2->user->user[0]->vhost,
1563 rep2->user->user[0]->username,
1564 rep2->user->user[0]->id,
1565 rep2->user->user[0]->ip,
1566 get_ip(rep2->user->user[0]->local_ip,
1567 rep2->user->user[0]->local_ip6));
1568
1569 entries_add(ctx, rep2->user->user[0]->username, strlen(rep2->user->user[0]->username), rep2->user->user[0]->id);
1570 } else {
1571 print_time_ival7(tmpbuf, time(0), rep2->user->user[0]->conn_time);
1572 printf("%s: disconnect user '%s' (%u) from %s with IP %s (reason: %s, time: %s)\n",
1573 rep2->user->user[0]->vhost,
1574 rep2->user->user[0]->username,
1575 rep2->user->user[0]->id,
1576 rep2->user->user[0]->ip,
1577 get_ip(rep2->user->user[0]->local_ip, rep2->user->user[0]->local_ip6),
1578 rep2->discon_reason_txt?rep2->discon_reason_txt:"unknown", tmpbuf);
1579 }
1580
1581 }
1582
1583 top_update_rep__free_unpacked(rep2, &pa);
1584 rep2 = NULL;
1585 }
1586
1587 tcsetattr(STDIN_FILENO, TCSANOW, &tio_old);
1588 ocsignal(SIGINT, old_sighandler);
1589 goto cleanup;
1590
1591 error:
1592 fprintf(stderr, ERR_SERVER_UNREACHABLE);
1593 ret = 1;
1594 cleanup:
1595 talloc_free(data);
1596 // These are indeed dead code but if removed a minor change
1597 // in the code above may result to either memory leak or
1598 // something worse.
1599 // coverity[dead_error_line : FALSE]
1600 if (rep1 != NULL)
1601 user_list_rep__free_unpacked(rep1, &pa);
1602 // coverity[dead_error_line : FALSE]
1603 if (rep2 != NULL)
1604 top_update_rep__free_unpacked(rep2, &pa);
1605 free_reply(&raw);
1606
1607 return ret;
1608 }
1609
handle_show_id_cmd(struct unix_ctx * ctx,const char * arg,cmd_params_st * params)1610 int handle_show_id_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
1611 {
1612 int ret;
1613 struct cmd_reply_st raw;
1614 UserListRep *rep = NULL;
1615 unsigned id;
1616 IdReq req = ID_REQ__INIT;
1617 PROTOBUF_ALLOCATOR(pa, ctx);
1618
1619 if (arg != NULL)
1620 id = atoi(arg);
1621
1622 if (arg == NULL || need_help(arg) || id == 0) {
1623 check_cmd_help(rl_line_buffer);
1624 return 1;
1625 }
1626
1627 init_reply(&raw);
1628
1629 req.id = id;
1630
1631 ret = send_cmd(ctx, CTL_CMD_ID_INFO, &req,
1632 (pack_size_func)id_req__get_packed_size,
1633 (pack_func)id_req__pack, &raw);
1634 if (ret < 0) {
1635 goto error;
1636 }
1637
1638 rep = user_list_rep__unpack(&pa, raw.data_size, raw.data);
1639 if (rep == NULL)
1640 goto error;
1641
1642 ret = common_info_cmd(rep, NULL, params);
1643 if (ret < 0)
1644 goto error;
1645
1646 goto cleanup;
1647
1648 error:
1649 fprintf(stderr, ERR_SERVER_UNREACHABLE);
1650 ret = 1;
1651 cleanup:
1652 if (rep != NULL)
1653 user_list_rep__free_unpacked(rep, &pa);
1654 free_reply(&raw);
1655
1656 return ret;
1657 }
1658
conn_prehandle(struct unix_ctx * ctx)1659 int conn_prehandle(struct unix_ctx *ctx)
1660 {
1661 ctx->fd = connect_to_ocserv(ctx->socket_file);
1662 if (ctx->fd != -1)
1663 ctx->is_open = 1;
1664
1665 return ctx->fd;
1666 }
1667
conn_posthandle(struct unix_ctx * ctx)1668 void conn_posthandle(struct unix_ctx *ctx)
1669 {
1670 if (ctx->is_open) {
1671 close(ctx->fd);
1672 ctx->is_open = 0;
1673 }
1674 }
1675
conn_init(void * pool,const char * file)1676 struct unix_ctx *conn_init(void *pool, const char *file)
1677 {
1678 struct unix_ctx *ctx;
1679 ctx = talloc_zero(pool, struct unix_ctx);
1680 if (ctx == NULL)
1681 return NULL;
1682 ctx->socket_file = file;
1683
1684 return ctx;
1685 }
1686
conn_close(struct unix_ctx * conn)1687 void conn_close(struct unix_ctx* conn)
1688 {
1689 talloc_free(conn);
1690 }
1691