10 #include "headers/shared.h"
13 #include "os_net/os_net.h"
14 #include "os_regex/os_regex.h"
16 #include "addagent/manage_agents.h"
18 #define IO_BUFFER_SIZE 0x10000
22 printf("\n%s %s: Connects to the manager to extract the agent key.\n", __ossec_name, ARGV0);
23 printf("Available options:\n");
24 printf("\t-h This help message.\n");
25 printf("\t-m <manager ip> Manager IP Address.\n");
26 printf("\t-p <port> Manager port (default 1515).\n");
27 printf("\t-A <agent name> Agent name (default is the hostname).\n");
28 printf("\t-P <pass> Authorization password.\n");
32 void SendSecurityToken(const int socket, SecBuffer *OutBuffers)
36 if (OutBuffers[0].cbBuffer != 0 && OutBuffers[0].pvBuffer != NULL)
38 sent = send(socket, OutBuffers[0].pvBuffer, OutBuffers[0].cbBuffer, 0);
40 ErrorExit("%s: Could not send security token to server (is ossec-authd running ?)", ARGV0);
43 FreeContextBuffer(OutBuffers[0].pvBuffer);
44 OutBuffers[0].pvBuffer = NULL;
45 OutBuffers[0].cbBuffer = 0;
49 void CreateSecureConnection(char *manager, char *port, int *socket, CtxtHandle *context, CredHandle *cred)
51 SECURITY_STATUS status;
52 SCHANNEL_CRED auth_cred;
53 DWORD input_flags = 0;
54 DWORD output_flags = 0;
57 SecBufferDesc OutBuffer;
58 SecBuffer OutBuffers[1];
59 SecBufferDesc InBuffer;
60 SecBuffer InBuffers[2];
63 // Get manager IP address
65 manager = OS_GetHost(manager, 3);
67 ErrorExit("%s: Could not resolve manager's hostname", ARGV0);
73 *socket = OS_ConnectTCP(port, manager);
76 ErrorExit("%s: Unable to connect to %s:%s", ARGV0, manager, port);
80 // Setting authentication credentials
82 ZeroMemory(&auth_cred, sizeof (auth_cred));
83 auth_cred.dwVersion = SCHANNEL_CRED_VERSION;
84 auth_cred.dwSessionLifespan = 60000;
85 auth_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION | SCH_CRED_NO_DEFAULT_CREDS | SCH_CRED_NO_SERVERNAME_CHECK;
87 status = AcquireCredentialsHandle(NULL, UNISP_NAME, SECPKG_CRED_OUTBOUND, NULL, &auth_cred, NULL, NULL, cred, NULL);
88 if (status != SEC_E_OK)
89 ErrorExit("%s: Could not acquire credentials (AcquireCredentialsHandle failed with error code 0x%lX", ARGV0, status);
93 // Initialize security context
95 OutBuffers[0].pvBuffer = NULL;
96 OutBuffers[0].BufferType = SECBUFFER_TOKEN;
97 OutBuffers[0].cbBuffer = 0;
99 OutBuffer.cBuffers = 1;
100 OutBuffer.pBuffers = OutBuffers;
101 OutBuffer.ulVersion = SECBUFFER_VERSION;
103 InBuffers[1].pvBuffer = NULL;
104 InBuffers[1].cbBuffer = 0;
105 InBuffers[1].BufferType = SECBUFFER_EMPTY;
107 buffer = LocalAlloc(LMEM_FIXED, IO_BUFFER_SIZE);
109 ErrorExit("%s: out of memory !", ARGV0);
111 input_flags = ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_CONFIDENTIALITY | ISC_REQ_INTEGRITY | ISC_REQ_MANUAL_CRED_VALIDATION | ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_STREAM;
112 status = InitializeSecurityContext(cred, NULL, NULL, input_flags, 0, 0, NULL, 0, context, &OutBuffer, &output_flags, NULL);
114 while (status != SEC_E_OK)
116 // See if we have a token to send to the server
117 if (status == SEC_I_CONTINUE_NEEDED)
119 SendSecurityToken(*socket, OutBuffers);
123 // See if we have data to retrieve from server
124 if ((total_read == 0) || (status == SEC_E_INCOMPLETE_MESSAGE))
126 read = recv(*socket, buffer + total_read, IO_BUFFER_SIZE - total_read, 0);
128 ErrorExit("%s: Could not get security token from server", ARGV0);
133 InBuffers[0].pvBuffer = buffer;
134 InBuffers[0].cbBuffer = total_read;
135 InBuffers[0].BufferType = SECBUFFER_TOKEN;
137 InBuffers[1].pvBuffer = NULL;
138 InBuffers[1].cbBuffer = 0;
139 InBuffers[1].BufferType = SECBUFFER_EMPTY;
141 InBuffer.cBuffers = 2;
142 InBuffer.pBuffers = InBuffers;
143 InBuffer.ulVersion = SECBUFFER_VERSION;
145 status = InitializeSecurityContext(cred, context, NULL, input_flags, 0, 0, &InBuffer, 0, context, &OutBuffer, &output_flags, NULL);
148 // Send remaining tokens if any
149 SendSecurityToken(*socket, OutBuffers);
151 printf("INFO: Connected to %s:%s\n", manager, port);
155 void SendSecureMessage(const int socket, CtxtHandle *context, const char *format, ...)
159 unsigned int buffer_length = 0;
160 unsigned int msg_length = 0;
162 SecPkgContext_StreamSizes sizes;
163 SECURITY_STATUS status;
165 SecBuffer msg_buffers[4];
167 va_start(args, format);
169 // Get sizes for given context
170 status = QueryContextAttributes(context, SECPKG_ATTR_STREAM_SIZES, &sizes);
171 if (status != SEC_E_OK)
172 ErrorExit("%s: Could not get message sizes (QueryContextAttributes failed with error code 0x%lX)", ARGV0, status);
175 buffer_length = sizes.cbHeader + sizes.cbMaximumMessage + sizes.cbTrailer;
176 buffer = LocalAlloc(LMEM_FIXED, buffer_length);
178 ErrorExit("%s: out of memory !", ARGV0);
179 vsnprintf(buffer + sizes.cbHeader, buffer_length - sizes.cbHeader, format, args);
180 msg_length = strlen(buffer + sizes.cbHeader);
182 // Encrypt message in place
183 msg_buffers[0].pvBuffer = buffer;
184 msg_buffers[0].cbBuffer = sizes.cbHeader;
185 msg_buffers[0].BufferType = SECBUFFER_STREAM_HEADER;
187 msg_buffers[1].pvBuffer = buffer + sizes.cbHeader;
188 msg_buffers[1].cbBuffer = msg_length;
189 msg_buffers[1].BufferType = SECBUFFER_DATA;
191 msg_buffers[2].pvBuffer = buffer + sizes.cbHeader + msg_length;
192 msg_buffers[2].cbBuffer = sizes.cbTrailer;
193 msg_buffers[2].BufferType = SECBUFFER_STREAM_TRAILER;
195 msg_buffers[3].BufferType = SECBUFFER_EMPTY;
197 msg.ulVersion = SECBUFFER_VERSION;
199 msg.pBuffers = msg_buffers;
201 status = EncryptMessage(context, 0, &msg, 0);
202 if (status != SEC_E_OK)
203 ErrorExit("%s: Could not encrypt message (EncryptMessage failed with error code %lX)", ARGV0, status);
205 sent = send(socket, buffer, msg_buffers[0].cbBuffer + msg_buffers[1].cbBuffer + msg_buffers[2].cbBuffer, 0);
207 ErrorExit("%s: Could not send message to server", ARGV0);
212 char *ReceiveSecureMessage(const int socket, CtxtHandle *context)
215 unsigned int buffer_length = 0;
218 char has_extra_data = 0;
219 SECURITY_STATUS status = SEC_E_INCOMPLETE_MESSAGE;
221 SecBuffer msg_buffers[4];
223 buffer = LocalAlloc(LMEM_FIXED, IO_BUFFER_SIZE);
225 while ((status == SEC_E_INCOMPLETE_MESSAGE) || (has_extra_data))
227 if (status == SEC_E_INCOMPLETE_MESSAGE)
229 read = recv(socket, buffer + buffer_length, IO_BUFFER_SIZE - buffer_length, 0);
231 ErrorExit("%s: Could not receive message from server (or invalid password)", ARGV0);
233 buffer_length += read;
236 msg_buffers[0].pvBuffer = buffer;
237 msg_buffers[0].cbBuffer = buffer_length;
238 msg_buffers[0].BufferType = SECBUFFER_DATA;
240 msg_buffers[1].BufferType = SECBUFFER_EMPTY;
241 msg_buffers[2].BufferType = SECBUFFER_EMPTY;
242 msg_buffers[3].BufferType = SECBUFFER_EMPTY;
244 msg.ulVersion = SECBUFFER_VERSION;
246 msg.pBuffers = msg_buffers;
248 status = DecryptMessage(context, &msg, 0, NULL);
250 if ((status != SEC_E_OK) && (status != SEC_E_INCOMPLETE_MESSAGE))
251 ErrorExit("%s: Could not decrypt received message (DecryptMessage failed with error code 0x%lX)", ARGV0, status);
253 if (status == SEC_E_OK)
256 for (i = 1; i < 4; ++i)
257 if (msg_buffers[i].BufferType == SECBUFFER_EXTRA)
260 memcpy(buffer, msg_buffers[i].pvBuffer, msg_buffers[i].cbBuffer);
261 buffer_length = msg_buffers[i].cbBuffer;
266 for (i = 1; i < 4; ++i)
267 if (msg_buffers[i].BufferType == SECBUFFER_DATA)
268 return msg_buffers[i].pvBuffer;
273 void InstallAuthKeys(char *msg)
275 if (strncmp(msg, "ERROR", 5) == 0)
276 ErrorExit("%s: %s (from manager)", ARGV0, msg);
277 else if (strncmp(msg, "OSSEC K:'", 9) == 0)
284 printf("INFO: Received response with agent key\n");
287 tmpstr = strchr(key, '\'');
290 ErrorExit("%s: Invalid key received. Closing connection.", ARGV0);
293 entry = OS_StrBreak(' ', key, 4);
295 if (!OS_IsValidID(entry[0]) || !OS_IsValidName(entry[1]) ||
296 !OS_IsValidName(entry[2]) || !OS_IsValidName(entry[3]))
297 ErrorExit("%s: Invalid key received (2). Closing connection.", ARGV0);
299 fp = fopen(KEYSFILE_PATH, "w");
302 ErrorExit("%s: Unable to open key file: %s", ARGV0, KEYSFILE_PATH);
304 fprintf(fp, "%s\n", key);
307 printf("INFO: Valid key created. Finished.\n");
310 ErrorExit("%s: Unknown message received (%s)", ARGV0, msg);
313 void DisconnectFromServer(const int socket, CtxtHandle *context, CredHandle *cred)
315 SecBufferDesc OutBuffer;
316 SecBuffer OutBuffers[1];
318 SECURITY_STATUS status;
323 dwType = SCHANNEL_SHUTDOWN;
325 OutBuffers[0].pvBuffer = &dwType;
326 OutBuffers[0].BufferType = SECBUFFER_TOKEN;
327 OutBuffers[0].cbBuffer = sizeof(dwType);
329 OutBuffer.cBuffers = 1;
330 OutBuffer.pBuffers = OutBuffers;
331 OutBuffer.ulVersion = SECBUFFER_VERSION;
333 status = ApplyControlToken(context, &OutBuffer);
334 if (status != SEC_E_OK)
335 ErrorExit("%s: Could not correclty close connection", ARGV0);
337 input_flags = ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_CONFIDENTIALITY | ISC_REQ_INTEGRITY | ISC_REQ_MANUAL_CRED_VALIDATION | ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_STREAM;
338 OutBuffers[0].pvBuffer = NULL;
339 OutBuffers[0].BufferType = SECBUFFER_TOKEN;
340 OutBuffers[0].cbBuffer = 0;
342 OutBuffer.cBuffers = 1;
343 OutBuffer.pBuffers = OutBuffers;
344 OutBuffer.ulVersion = SECBUFFER_VERSION;
346 status = InitializeSecurityContext(cred, context, NULL, input_flags, 0, 0, NULL, 0, context, &OutBuffer, &output_flags, NULL);
347 if (status != SEC_E_OK)
348 ErrorExit("%s: Could not correclty close connection (2)", ARGV0);
350 sent = send(socket, OutBuffers[0].pvBuffer, OutBuffers[0].cbBuffer, 0);
352 ErrorExit("%s: Could not correclty close connection (3)", ARGV0);
354 FreeContextBuffer(OutBuffers[0].pvBuffer);
355 DeleteSecurityContext(context);
359 int main(int argc, char **argv)
365 char *manager = NULL;
366 char *agentname = NULL;
369 char *authpass = NULL;
370 char buf[4096 + 1] = { '\0' };
375 /* Setting the name */
378 while((c = getopt(argc, argv, "hm:p:A:P:")) != -1)
386 ErrorExit("%s: -%c needs an argument",ARGV0, c);
391 ErrorExit("%s: -%c needs an argument",ARGV0, c);
396 ErrorExit("%s: -%c needs an argument",ARGV0, c);
398 tmp_port = atoi(optarg);
399 if(tmp_port <= 0 || tmp_port >= 65536)
401 ErrorExit("%s: Invalid port: %s", ARGV0, optarg);
408 ErrorExit("%s: -%c needs an argument", ARGV0, c);
418 // Initialize Windows Networking
419 error = WSAStartup(MAKEWORD(2, 2), &wsa);
421 ErrorExit("%s: Could not initialize networking (WSAStartup failed with error code %u)", ARGV0, error);
423 // Determine agent_name
424 if(agentname == NULL)
426 if(gethostname(hostname, 512) != 0)
427 ErrorExit("%s: ERROR: Unable to extract hostname. Custom agent name not set.", ARGV0);
429 agentname = hostname;
432 /* Checking if there is a custom password file */
433 if (authpass == NULL) {
435 fp = fopen(AUTHDPASS_PATH, "r");
440 char *ret = fgets(buf, 4095, fp);
442 if (ret && strlen(buf) > 2) {
447 printf("INFO: Using password specified on file: %s\n", AUTHDPASS_PATH);
451 printf("WARN: No authentication password provided. Insecure mode started.\n");
455 // Connect to socket and init security context
456 CreateSecureConnection(manager, port, &socket, &context, &cred);
458 printf("INFO: Using agent name as: %s\n", agentname);
463 SendSecureMessage(socket, &context, "OSSEC PASS: %s OSSEC A:'%s'\n", authpass, agentname);
465 SendSecureMessage(socket, &context, "OSSEC A:'%s'\n", agentname);
467 printf("INFO: Sent request to manager. Waiting for reply.\n");
470 msg = ReceiveSecureMessage(socket, &context);
472 // Install received keys
473 InstallAuthKeys(msg);
476 DisconnectFromServer(socket, &context, &cred);