whitelist: Make sure listed IDs are null-terminated.
[strongswan.git] / src / libcharon / plugins / whitelist / whitelist.c
1 /*
2 * Copyright (C) 2011 Martin Willi
3 * Copyright (C) 2011 revosec AG
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "whitelist_msg.h"
17
18 #include <sys/socket.h>
19 #include <sys/un.h>
20 #include <unistd.h>
21 #include <stddef.h>
22 #include <stdio.h>
23 #include <errno.h>
24
25 /**
26 * Connect to the daemon, return FD
27 */
28 static int make_connection()
29 {
30 struct sockaddr_un addr;
31 int fd;
32
33 addr.sun_family = AF_UNIX;
34 strcpy(addr.sun_path, WHITELIST_SOCKET);
35
36 fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
37 if (fd < 0)
38 {
39 fprintf(stderr, "opening socket failed: %s\n", strerror(errno));
40 return -1;
41 }
42 if (connect(fd, (struct sockaddr *)&addr,
43 offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path)) < 0)
44 {
45 fprintf(stderr, "connecting to %s failed: %s\n",
46 WHITELIST_SOCKET, strerror(errno));
47 close(fd);
48 return -1;
49 }
50 return fd;
51 }
52
53 /**
54 * Send a single message
55 */
56 static int send_msg(int type, char *id)
57 {
58 whitelist_msg_t msg = {
59 .type = type,
60 };
61 int fd;
62
63 fd = make_connection();
64 if (fd == -1)
65 {
66 return 2;
67 }
68 snprintf(msg.id, sizeof(msg.id), "%s", id);
69 if (send(fd, &msg, sizeof(msg), 0) != sizeof(msg))
70 {
71 fprintf(stderr, "writing to socket failed: %s\n", strerror(errno));
72 close(fd);
73 return 2;
74 }
75 if (type == WHITELIST_LIST)
76 {
77 while (recv(fd, &msg, sizeof(msg), 0) == sizeof(msg))
78 {
79 if (msg.type != WHITELIST_LIST)
80 {
81 break;
82 }
83 msg.id[sizeof(msg.id) - 1] = '\0';
84 printf("%s\n", msg.id);
85 }
86 }
87 close(fd);
88 return 0;
89 }
90
91 /**
92 * Send a batch of messages, reading identities from a file
93 */
94 static int send_batch(int type, char *file)
95 {
96 whitelist_msg_t msg = {
97 .type = type,
98 };
99 FILE *f = stdin;
100 int fd, len;
101
102 fd = make_connection();
103 if (fd == -1)
104 {
105 return 2;
106 }
107 if (file)
108 {
109 f = fopen(file, "r");
110 if (f == NULL)
111 {
112 fprintf(stderr, "opening %s failed: %s\n", file, strerror(errno));
113 close(fd);
114 return 3;
115 }
116 }
117 while (fgets(msg.id, sizeof(msg.id), f))
118 {
119 len = strlen(msg.id);
120 if (len == 0)
121 {
122 continue;
123 }
124 if (msg.id[len-1] == '\n')
125 {
126 msg.id[len-1] = '\0';
127 }
128 if (send(fd, &msg, sizeof(msg), 0) != sizeof(msg))
129 {
130 fprintf(stderr, "writing to socket failed: %s\n", strerror(errno));
131 if (f != stdin)
132 {
133 fclose(f);
134 }
135 close(fd);
136 return 2;
137 }
138 }
139 if (f != stdin)
140 {
141 fclose(f);
142 }
143 close(fd);
144 return 0;
145 }
146
147 int main(int argc, char *argv[])
148 {
149 if (argc == 3 && strcmp(argv[1], "add") == 0)
150 {
151 return send_msg(WHITELIST_ADD, argv[2]);
152 }
153 if (argc == 3 && strcmp(argv[1], "remove") == 0)
154 {
155 return send_msg(WHITELIST_REMOVE, argv[2]);
156 }
157 if ((argc == 2 || argc == 3) && strcmp(argv[1], "add-from") == 0)
158 {
159 return send_batch(WHITELIST_ADD, argc == 3 ? argv[2] : NULL);
160 }
161 if ((argc == 2 || argc == 3) && strcmp(argv[1], "remove-from") == 0)
162 {
163 return send_batch(WHITELIST_REMOVE, argc == 3 ? argv[2] : NULL);
164 }
165 if ((argc == 2 || argc == 3) && strcmp(argv[1], "flush") == 0)
166 {
167 return send_msg(WHITELIST_FLUSH, argc == 3 ? argv[2] : "%any");
168 }
169 if ((argc == 2 || argc == 3) && strcmp(argv[1], "list") == 0)
170 {
171 return send_msg(WHITELIST_LIST, argc == 3 ? argv[2] : "%any");
172 }
173 if (argc == 2 && strcmp(argv[1], "enable") == 0)
174 {
175 return send_msg(WHITELIST_ENABLE, "");
176 }
177 if (argc == 2 && strcmp(argv[1], "disable") == 0)
178 {
179 return send_msg(WHITELIST_DISABLE, "");
180 }
181 fprintf(stderr, "Usage:\n");
182 fprintf(stderr, " %s add <identity>\n", argv[0]);
183 fprintf(stderr, " %s remove <identity>\n", argv[0]);
184 fprintf(stderr, " %s add-from <file>\n", argv[0]);
185 fprintf(stderr, " %s remove-from <file>\n", argv[0]);
186 fprintf(stderr, " %s flush [<pattern>]\n", argv[0]);
187 fprintf(stderr, " %s list [<pattern>]\n", argv[0]);
188 fprintf(stderr, " %s enable\n", argv[0]);
189 fprintf(stderr, " %s disable\n", argv[0]);
190 return 1;
191 }