Browse Source

[syslog] Add basic support for encrypted syslog via TLS

Encrypted syslog seems not yet to be standardised, but is supported by
some existing syslog servers.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 years ago
parent
commit
943b3003bd
4 changed files with 282 additions and 0 deletions
  1. 3
    0
      src/config/config.c
  2. 1
    0
      src/config/console.h
  3. 3
    0
      src/include/ipxe/dhcp.h
  4. 275
    0
      src/net/tcp/syslogs.c

+ 3
- 0
src/config/config.c View File

@@ -77,6 +77,9 @@ REQUIRE_OBJECT ( pc_kbd );
77 77
 #ifdef CONSOLE_SYSLOG
78 78
 REQUIRE_OBJECT ( syslog );
79 79
 #endif
80
+#ifdef CONSOLE_SYSLOGS
81
+REQUIRE_OBJECT ( syslogs );
82
+#endif
80 83
 #ifdef CONSOLE_EFI
81 84
 REQUIRE_OBJECT ( efi_console );
82 85
 #endif

+ 1
- 0
src/config/console.h View File

@@ -19,6 +19,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
19 19
 //#define	CONSOLE_DIRECT_VGA	/* Direct access to VGA card */
20 20
 //#define	CONSOLE_PC_KBD		/* Direct access to PC keyboard */
21 21
 //#define	CONSOLE_SYSLOG		/* Syslog console */
22
+//#define	CONSOLE_SYSLOGS		/* Encrypted syslog console */
22 23
 //#define	CONSOLE_VMWARE		/* VMware logfile console */
23 24
 
24 25
 #define	KEYBOARD_MAP	us

+ 3
- 0
src/include/ipxe/dhcp.h View File

@@ -352,6 +352,9 @@ struct dhcp_client_uuid {
352 352
  */
353 353
 #define DHCP_EB_SCRIPTLET DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x51 )
354 354
 
355
+/** Encrypted syslog server */
356
+#define DHCP_EB_SYSLOGS_SERVER DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x55 )
357
+
355 358
 /** Skip PXE DHCP protocol extensions such as ProxyDHCP
356 359
  *
357 360
  * If set to a non-zero value, iPXE will not wait for ProxyDHCP offers

+ 275
- 0
src/net/tcp/syslogs.c View File

@@ -0,0 +1,275 @@
1
+/*
2
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+FILE_LICENCE ( GPL2_OR_LATER );
20
+
21
+/** @file
22
+ *
23
+ * Encrypted syslog protocol
24
+ *
25
+ */
26
+
27
+#include <stdint.h>
28
+#include <stdlib.h>
29
+#include <byteswap.h>
30
+#include <ipxe/xfer.h>
31
+#include <ipxe/open.h>
32
+#include <ipxe/tcpip.h>
33
+#include <ipxe/dhcp.h>
34
+#include <ipxe/settings.h>
35
+#include <ipxe/console.h>
36
+#include <ipxe/lineconsole.h>
37
+#include <ipxe/tls.h>
38
+#include <ipxe/syslog.h>
39
+#include <config/console.h>
40
+
41
+/* Set default console usage if applicable */
42
+#if ! ( defined ( CONSOLE_SYSLOGS ) && CONSOLE_EXPLICIT ( CONSOLE_SYSLOGS ) )
43
+#undef CONSOLE_SYSLOGS
44
+#define CONSOLE_SYSLOGS ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_TUI )
45
+#endif
46
+
47
+struct console_driver syslogs_console __console_driver;
48
+
49
+/** The encrypted syslog server */
50
+static struct sockaddr_tcpip logserver = {
51
+	.st_family = AF_INET,
52
+	.st_port = htons ( SYSLOG_PORT ),
53
+};
54
+
55
+/**
56
+ * Handle encrypted syslog TLS interface close
57
+ *
58
+ * @v intf		Interface
59
+ * @v rc		Reason for close
60
+ */
61
+static void syslogs_close ( struct interface *intf __unused, int rc ) {
62
+
63
+	DBG ( "SYSLOGS console disconnected: %s\n", strerror ( rc ) );
64
+}
65
+
66
+/**
67
+ * Handle encrypted syslog TLS interface window change
68
+ *
69
+ * @v intf		Interface
70
+ */
71
+static void syslogs_window_changed ( struct interface *intf ) {
72
+
73
+	/* Mark console as enabled when window first opens, indicating
74
+	 * that TLS negotiation is complete.  (Do not disable console
75
+	 * when window closes again, since TCP will close the window
76
+	 * whenever there is unACKed data.)
77
+	 */
78
+	if ( xfer_window ( intf ) ) {
79
+		if ( syslogs_console.disabled )
80
+			DBG ( "SYSLOGS console connected\n" );
81
+		syslogs_console.disabled = 0;
82
+	}
83
+}
84
+
85
+/** Encrypted syslog TLS interface operations */
86
+static struct interface_operation syslogs_operations[] = {
87
+	INTF_OP ( xfer_window_changed, struct interface *,
88
+		  syslogs_window_changed ),
89
+	INTF_OP ( intf_close, struct interface *, syslogs_close ),
90
+};
91
+
92
+/** Encrypted syslog TLS interface descriptor */
93
+static struct interface_descriptor syslogs_desc =
94
+	INTF_DESC_PURE ( syslogs_operations );
95
+
96
+/** The encrypted syslog TLS interface */
97
+static struct interface syslogs = INTF_INIT ( syslogs_desc );
98
+
99
+/******************************************************************************
100
+ *
101
+ * Console driver
102
+ *
103
+ ******************************************************************************
104
+ */
105
+
106
+/** Encrypted syslog line buffer */
107
+static char syslogs_buffer[SYSLOG_BUFSIZE];
108
+
109
+/** Encrypted syslog severity */
110
+static unsigned int syslogs_severity = SYSLOG_DEFAULT_SEVERITY;
111
+
112
+/**
113
+ * Handle ANSI set encrypted syslog priority (private sequence)
114
+ *
115
+ * @v count		Parameter count
116
+ * @v params		List of graphic rendition aspects
117
+ */
118
+static void syslogs_handle_priority ( unsigned int count __unused,
119
+				      int params[] ) {
120
+	if ( params[0] >= 0 ) {
121
+		syslogs_severity = params[0];
122
+	} else {
123
+		syslogs_severity = SYSLOG_DEFAULT_SEVERITY;
124
+	}
125
+}
126
+
127
+/** Encrypted syslog ANSI escape sequence handlers */
128
+static struct ansiesc_handler syslogs_handlers[] = {
129
+	{ ANSIESC_LOG_PRIORITY, syslogs_handle_priority },
130
+	{ 0, NULL }
131
+};
132
+
133
+/** Encrypted syslog line console */
134
+static struct line_console syslogs_line = {
135
+	.buffer = syslogs_buffer,
136
+	.len = sizeof ( syslogs_buffer ),
137
+	.ctx = {
138
+		.handlers = syslogs_handlers,
139
+	},
140
+};
141
+
142
+/** Encrypted syslog recursion marker */
143
+static int syslogs_entered;
144
+
145
+/**
146
+ * Print a character to encrypted syslog console
147
+ *
148
+ * @v character		Character to be printed
149
+ */
150
+static void syslogs_putchar ( int character ) {
151
+	int rc;
152
+
153
+	/* Ignore if we are already mid-logging */
154
+	if ( syslogs_entered )
155
+		return;
156
+
157
+	/* Fill line buffer */
158
+	if ( line_putchar ( &syslogs_line, character ) == 0 )
159
+		return;
160
+
161
+	/* Guard against re-entry */
162
+	syslogs_entered = 1;
163
+
164
+	/* Send log message */
165
+	if ( ( rc = xfer_printf ( &syslogs, "<%d>ipxe: %s\n",
166
+				  SYSLOG_PRIORITY ( SYSLOG_DEFAULT_FACILITY,
167
+						    syslogs_severity ),
168
+				  syslogs_buffer ) ) != 0 ) {
169
+		DBG ( "SYSLOGS could not send log message: %s\n",
170
+		      strerror ( rc ) );
171
+	}
172
+
173
+	/* Clear re-entry flag */
174
+	syslogs_entered = 0;
175
+}
176
+
177
+/** Encrypted syslog console driver */
178
+struct console_driver syslogs_console __console_driver = {
179
+	.putchar = syslogs_putchar,
180
+	.disabled = 1,
181
+	.usage = CONSOLE_SYSLOGS,
182
+};
183
+
184
+/******************************************************************************
185
+ *
186
+ * Settings
187
+ *
188
+ ******************************************************************************
189
+ */
190
+
191
+/** Encrypted syslog server setting */
192
+struct setting syslogs_setting __setting ( SETTING_MISC ) = {
193
+	.name = "syslogs",
194
+	.description = "Encrypted syslog server",
195
+	.tag = DHCP_EB_SYSLOGS_SERVER,
196
+	.type = &setting_type_string,
197
+};
198
+
199
+/**
200
+ * Apply encrypted syslog settings
201
+ *
202
+ * @ret rc		Return status code
203
+ */
204
+static int apply_syslogs_settings ( void ) {
205
+	static char *old_server;
206
+	char *server;
207
+	struct interface *socket;
208
+	int len;
209
+	int rc;
210
+
211
+	/* Fetch log server */
212
+	len = fetch_string_setting_copy ( NULL, &syslogs_setting, &server );
213
+	if ( len < 0 ) {
214
+		rc = len;
215
+		goto err_fetch_server;
216
+	}
217
+
218
+	/* Do nothing unless log server has changed */
219
+	if ( ( ( server == NULL ) && ( old_server == NULL ) ) ||
220
+	     ( ( server != NULL ) && ( old_server != NULL ) &&
221
+	       ( strcmp ( server, old_server ) == 0 ) ) ) {
222
+		rc = 0;
223
+		goto out_no_change;
224
+	}
225
+	free ( old_server );
226
+	old_server = NULL;
227
+
228
+	/* Reset encrypted syslog connection */
229
+	syslogs_console.disabled = 1;
230
+	intf_restart ( &syslogs, 0 );
231
+
232
+	/* Do nothing unless we have a log server */
233
+	if ( ! server ) {
234
+		DBG ( "SYSLOGS has no log server\n" );
235
+		rc = 0;
236
+		goto out_no_server;
237
+	}
238
+
239
+	/* Add TLS filter */
240
+	if ( ( rc = add_tls ( &syslogs, server, &socket ) ) != 0 ) {
241
+		DBG ( "SYSLOGS cannot create TLS filter: %s\n",
242
+		      strerror ( rc ) );
243
+		goto err_add_tls;
244
+	}
245
+
246
+	/* Connect to log server */
247
+	if ( ( rc = xfer_open_named_socket ( socket, SOCK_STREAM,
248
+					     (( struct sockaddr *) &logserver ),
249
+					     server, NULL ) ) != 0 ) {
250
+		DBG ( "SYSLOGS cannot connect to log server: %s\n",
251
+		      strerror ( rc ) );
252
+		goto err_open_named_socket;
253
+	}
254
+	DBG ( "SYSLOGS using log server %s\n", server );
255
+
256
+	/* Record log server */
257
+	old_server = server;
258
+	server = NULL;
259
+
260
+	/* Success */
261
+	rc = 0;
262
+
263
+ err_open_named_socket:
264
+ err_add_tls:
265
+ out_no_server:
266
+ out_no_change:
267
+	free ( server );
268
+ err_fetch_server:
269
+	return rc;
270
+}
271
+
272
+/** Encrypted syslog settings applicator */
273
+struct settings_applicator syslogs_applicator __settings_applicator = {
274
+	.apply = apply_syslogs_settings,
275
+};

Loading…
Cancel
Save