1 /*****************************************************************************\
2 * $Id: ipmiconsole_packet.c,v 1.64 2010-08-03 00:10:59 chu11 Exp $
3 *****************************************************************************
4 * Copyright (C) 2007-2015 Lawrence Livermore National Security, LLC.
5 * Copyright (C) 2006-2007 The Regents of the University of California.
6 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
7 * Written by Albert Chu <chu11@llnl.gov>
8 * UCRL-CODE-221226
9 *
10 * This file is part of Ipmiconsole, a set of IPMI 2.0 SOL libraries
11 * and utilities. For details, see http://www.llnl.gov/linux/.
12 *
13 * Ipmiconsole is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 3 of the License, or (at your
16 * option) any later version.
17 *
18 * Ipmiconsole is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
22 *
23 * You should have received a copy of the GNU General Public License along
24 * with Ipmiconsole. If not, see <http://www.gnu.org/licenses/>.
_crypt_gensalt_traditional_rn(unsigned long count,const char * input,int size,char * output,int output_size)25 \*****************************************************************************/
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif /* HAVE_CONFIG_H */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <stdint.h>
34 #if STDC_HEADERS
35 #include <string.h>
36 #endif /* STDC_HEADERS */
37 #include <assert.h>
38 #include <errno.h>
39 #if HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif /* HAVE_UNISTD_H */
42
43 #include "ipmiconsole.h"
44 #include "ipmiconsole_defs.h"
45
46 #include "ipmiconsole_packet.h"
47 #include "ipmiconsole_ctx.h"
48 #include "ipmiconsole_debug.h"
49
50 #include "freeipmi-portability.h"
51 #include "cbuf.h"
52 #include "debug-util.h"
53 #include "secure.h"
54
55 #define IPMICONSOLE_MAX_PACKET_DUMP_HDR_LEN 1024
56
57 fiid_field_t *
58 ipmiconsole_packet_template (ipmiconsole_ctx_t c,
59 ipmiconsole_packet_type_t p)
60 {
61 assert (c);
62 assert (c->magic == IPMICONSOLE_CTX_MAGIC);
63 assert (IPMICONSOLE_PACKET_TYPE_VALID (p));
64
65 switch (p)
66 {
67 case IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RQ:
68 return (&tmpl_cmd_get_channel_authentication_capabilities_rq[0]);
69 case IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RS:
70 return (&tmpl_cmd_get_channel_authentication_capabilities_rs[0]);
71 case IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_REQUEST:
72 return (&tmpl_rmcpplus_open_session_request[0]);
73 case IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_RESPONSE:
74 return (&tmpl_rmcpplus_open_session_response[0]);
75 case IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1:
76 return (&tmpl_rmcpplus_rakp_message_1[0]);
77 case IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_2:
78 return (&tmpl_rmcpplus_rakp_message_2[0]);
79 case IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_3:
80 return (&tmpl_rmcpplus_rakp_message_3[0]);
81 case IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_4:
82 return (&tmpl_rmcpplus_rakp_message_4[0]);
83 case IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RQ:
84 return (&tmpl_cmd_set_session_privilege_level_rq[0]);
85 case IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS:
86 return (&tmpl_cmd_set_session_privilege_level_rs[0]);
87 case IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RQ:
88 return (&tmpl_cmd_get_channel_payload_support_rq[0]);
89 case IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RS:
90 return (&tmpl_cmd_get_channel_payload_support_rs[0]);
91 case IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RQ:
92 return (&tmpl_cmd_get_payload_activation_status_rq[0]);
93 case IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RS:
94 return (&tmpl_cmd_get_payload_activation_status_rs[0]);
95 case IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RQ:
96 return (&tmpl_cmd_activate_payload_sol_rq[0]);
97 case IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS:
98 return (&tmpl_cmd_activate_payload_sol_rs[0]);
99 case IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RQ:
100 return (&tmpl_sol_payload_data_remote_console_to_bmc[0]);
101 case IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RS:
102 return (&tmpl_sol_payload_data_bmc_to_remote_console[0]);
103 case IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RQ:
104 return (&tmpl_cmd_get_channel_payload_version_rq[0]);
105 case IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RS:
106 return (&tmpl_cmd_get_channel_payload_version_rs[0]);
107 case IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RQ:
108 return (&tmpl_cmd_deactivate_payload_rq[0]);
109 case IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RS:
110 return (&tmpl_cmd_deactivate_payload_rs[0]);
111 case IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RQ:
112 return (&tmpl_cmd_chassis_control_rq[0]);
113 case IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RS:
114 return (&tmpl_cmd_chassis_control_rs[0]);
115 default:
116 IPMICONSOLE_CTX_DEBUG (c, ("invalid packet type: %d", p));
117 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
118 return (NULL);
119 }
120
121 return (NULL); /* NOT REACHED */
122 }
123
BF_encode(char * dst,const BF_word * src,int size)124 fiid_obj_t
125 ipmiconsole_packet_object (ipmiconsole_ctx_t c,
126 ipmiconsole_packet_type_t p)
127 {
128 assert (c);
129 assert (c->magic == IPMICONSOLE_CTX_MAGIC);
130 assert (IPMICONSOLE_PACKET_TYPE_VALID (p));
131
132 switch (p)
133 {
134 case IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RQ:
135 return (c->connection.obj_authentication_capabilities_rq);
136 case IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RS:
137 return (c->connection.obj_authentication_capabilities_rs);
138 case IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_REQUEST:
139 return (c->connection.obj_open_session_request);
140 case IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_RESPONSE:
141 return (c->connection.obj_open_session_response);
142 case IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1:
143 return (c->connection.obj_rakp_message_1);
144 case IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_2:
145 return (c->connection.obj_rakp_message_2);
146 case IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_3:
147 return (c->connection.obj_rakp_message_3);
148 case IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_4:
149 return (c->connection.obj_rakp_message_4);
150 case IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RQ:
151 return (c->connection.obj_set_session_privilege_level_rq);
152 case IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS:
153 return (c->connection.obj_set_session_privilege_level_rs);
154 case IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RQ:
155 return (c->connection.obj_get_channel_payload_support_rq);
156 case IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RS:
157 return (c->connection.obj_get_channel_payload_support_rs);
158 case IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RQ:
159 return (c->connection.obj_get_payload_activation_status_rq);
160 case IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RS:
161 return (c->connection.obj_get_payload_activation_status_rs);
162 case IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RQ:
163 return (c->connection.obj_activate_payload_rq);
164 case IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS:
165 return (c->connection.obj_activate_payload_rs);
166 case IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RQ:
167 return (c->connection.obj_sol_payload_data_rq);
168 case IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RS:
169 return (c->connection.obj_sol_payload_data_rs);
170 case IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RQ:
171 return (c->connection.obj_get_channel_payload_version_rq);
172 case IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RS:
173 return (c->connection.obj_get_channel_payload_version_rs);
174 case IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RQ:
175 return (c->connection.obj_deactivate_payload_rq);
176 case IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RS:
177 return (c->connection.obj_deactivate_payload_rs);
178 case IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RQ:
179 return (c->connection.obj_close_session_rq);
180 case IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RS:
181 return (c->connection.obj_close_session_rs);
182 default:
183 IPMICONSOLE_CTX_DEBUG (c, ("invalid packet type: %d", p));
184 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
185 return (NULL);
186 }
187
188 return (NULL); /* NOT REACHED */
189 }
190
191 static int
192 _packet_dump_hdr (ipmiconsole_ctx_t c,
193 ipmiconsole_packet_type_t p,
194 char *hdr,
195 unsigned int hdrlen)
196 {
197 uint8_t packet_type;
198 uint8_t packet_direction;
199 const char *str_cmd = NULL;
200
201 assert (c);
202 assert (c->magic == IPMICONSOLE_CTX_MAGIC);
203 assert (IPMICONSOLE_PACKET_TYPE_VALID (p));
204 assert (hdr);
205 assert (hdrlen);
206
207 if (p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RQ
208 || p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RS)
209 packet_type = DEBUG_UTIL_TYPE_IPMI_1_5;
210 else
211 packet_type = DEBUG_UTIL_TYPE_IPMI_2_0;
212
213 switch (p)
214 {
215 case IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RQ:
216 case IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RS:
217 str_cmd = ipmi_cmd_str (IPMI_NET_FN_APP_RQ, IPMI_CMD_GET_CHANNEL_AUTHENTICATION_CAPABILITIES);
218 break;
219 case IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_REQUEST:
220 case IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_RESPONSE:
221 str_cmd = DEBUG_UTIL_OPEN_SESSION_STR;
222 break;
223 case IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1:
224 str_cmd = DEBUG_UTIL_RAKP_1_STR;
225 break;
226 case IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_2:
227 str_cmd = DEBUG_UTIL_RAKP_2_STR;
228 break;
229 case IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_3:
230 str_cmd = DEBUG_UTIL_RAKP_3_STR;
231 break;
232 case IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_4:
233 str_cmd = DEBUG_UTIL_RAKP_4_STR;
234 break;
235 case IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RQ:
236 case IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS:
237 str_cmd = ipmi_cmd_str (IPMI_NET_FN_APP_RQ, IPMI_CMD_SET_SESSION_PRIVILEGE_LEVEL);
238 break;
239 case IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RQ:
240 case IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RS:
241 str_cmd = ipmi_cmd_str (IPMI_NET_FN_APP_RQ, IPMI_CMD_GET_CHANNEL_PAYLOAD_SUPPORT);
242 break;
243 case IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RQ:
244 case IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RS:
245 str_cmd = ipmi_cmd_str (IPMI_NET_FN_APP_RQ, IPMI_CMD_GET_PAYLOAD_ACTIVATION_STATUS);
246 break;
247 case IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RQ:
248 case IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS:
249 str_cmd = ipmi_cmd_str (IPMI_NET_FN_APP_RQ, IPMI_CMD_ACTIVATE_PAYLOAD);
250 break;
251 case IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RQ:
252 str_cmd = "SOL Remote Console to BMC";
253 break;
254 case IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RS:
255 str_cmd = "SOL BMC to Remote Console";
256 break;
257 case IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RQ:
258 case IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RS:
259 str_cmd = ipmi_cmd_str (IPMI_NET_FN_APP_RQ, IPMI_CMD_GET_CHANNEL_PAYLOAD_VERSION);
260 break;
261 case IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RQ:
262 case IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RS:
263 str_cmd = ipmi_cmd_str (IPMI_NET_FN_APP_RQ, IPMI_CMD_DEACTIVATE_PAYLOAD);
264 break;
265 case IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RQ:
266 case IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RS:
267 str_cmd = ipmi_cmd_str (IPMI_NET_FN_APP_RQ, IPMI_CMD_CLOSE_SESSION);
268 break;
269 default:
270 IPMICONSOLE_CTX_DEBUG (c, ("invalid packet type: %d", p));
271 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
272 return (-1);
273 }
274
275 /* special case: there is no "Request/Response" with SOL data */
276 if (p == IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RQ
277 || p == IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RS)
278 packet_direction = DEBUG_UTIL_DIRECTION_NONE;
279 else if (IPMICONSOLE_PACKET_TYPE_REQUEST (p))
280 packet_direction = DEBUG_UTIL_DIRECTION_REQUEST;
281 else
282 packet_direction = DEBUG_UTIL_DIRECTION_RESPONSE;
283
284 if (debug_hdr_str (packet_type,
285 packet_direction,
286 DEBUG_UTIL_FLAGS_DEFAULT,
287 str_cmd,
288 hdr,
289 hdrlen) < 0)
290 {
291 IPMICONSOLE_CTX_DEBUG (c, ("debug_hdr_str: p = %d", p));
292 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
293 return (-1);
294 }
295
296 return (0);
297 }
298
299 int
300 ipmiconsole_packet_dump (ipmiconsole_ctx_t c,
301 ipmiconsole_packet_type_t p,
302 const void *buf,
303 unsigned int buflen)
304 {
305 fiid_field_t *tmpl_lan_msg_hdr;
306 fiid_field_t *tmpl_cmd;
307 char hdr[IPMICONSOLE_MAX_PACKET_DUMP_HDR_LEN];
308 int fd;
309
310 assert (c);
311 assert (c->magic == IPMICONSOLE_CTX_MAGIC);
312 assert (IPMICONSOLE_PACKET_TYPE_VALID (p));
313 assert (buf);
314 assert (buflen);
315
316 if (c->config.debug_flags & IPMICONSOLE_DEBUG_STDOUT)
317 fd = STDOUT_FILENO;
318 else if (c->config.debug_flags & IPMICONSOLE_DEBUG_STDERR)
319 fd = STDERR_FILENO;
320 else if (c->config.debug_flags & IPMICONSOLE_DEBUG_FILE)
321 fd = c->debug.debug_fd;
322 else
323 return (0);
324
325 tmpl_cmd = ipmiconsole_packet_template (c, p);
326
327 if (IPMICONSOLE_PACKET_TYPE_REQUEST (p))
328 tmpl_lan_msg_hdr = &tmpl_lan_msg_hdr_rq[0];
329 else
330 tmpl_lan_msg_hdr = &tmpl_lan_msg_hdr_rs[0];
331
332 if (_packet_dump_hdr (c, p, hdr, IPMICONSOLE_MAX_PACKET_DUMP_HDR_LEN) < 0)
333 return (-1);
334
335 /* IPMI 1.5 Style Packets */
336 if (p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RQ
337 || p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RS)
338 {
339 if (ipmi_dump_lan_packet (fd,
340 c->config.hostname,
341 hdr,
342 NULL,
343 buf,
344 buflen,
345 tmpl_lan_msg_hdr,
346 tmpl_cmd) < 0)
347 {
348 IPMICONSOLE_CTX_DEBUG (c, ("ipmi_dump_lan_packet: p = %d; %s", p, strerror (errno)));
349 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
350 return (-1);
351 }
352 }
353 else /* IPMI 2.0 Style Packets */
354 {
355 /* IPMI 2.0 RAKP Session Setup Packets use no cipher
356 * algorithms
357 */
358 if (p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_REQUEST
359 || p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_RESPONSE
360 || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1
361 || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_2
362 || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_3
363 || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_4)
364 {
365 if (ipmi_dump_rmcpplus_packet (fd,
366 c->config.hostname,
367 hdr,
368 NULL,
369 IPMI_AUTHENTICATION_ALGORITHM_RAKP_NONE,
370 IPMI_INTEGRITY_ALGORITHM_NONE,
371 IPMI_CONFIDENTIALITY_ALGORITHM_NONE,
372 NULL,
373 0,
374 NULL,
375 0,
376 buf,
377 buflen,
378 tmpl_lan_msg_hdr,
379 tmpl_cmd) < 0)
380 {
381 IPMICONSOLE_CTX_DEBUG (c, ("ipmi_dump_rmcpplus_packet: p = %d; %s", p, strerror (errno)));
382 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
383 return (-1);
384 }
385 }
386 else
387 {
388 if (ipmi_dump_rmcpplus_packet (fd,
389 c->config.hostname,
390 hdr,
391 NULL,
392 c->config.authentication_algorithm,
393 c->config.integrity_algorithm,
394 c->config.confidentiality_algorithm,
395 c->session.integrity_key_ptr,
396 c->session.integrity_key_len,
397 c->session.confidentiality_key_ptr,
398 c->session.confidentiality_key_len,
399 buf,
400 buflen,
401 tmpl_lan_msg_hdr,
402 tmpl_cmd) < 0)
403 {
404 IPMICONSOLE_CTX_DEBUG (c, ("ipmi_dump_rmcpplus_packet: p = %d; %s", p, strerror (errno)));
405 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
406 return (-1);
407 }
408
409 }
410 }
411
412 return (0);
413 }
414
415 static int
416 _packet_dump_unknown_hdr (ipmiconsole_ctx_t c,
417 const void *buf,
418 unsigned int buflen,
419 char *hdr,
420 unsigned int hdrlen)
421 {
422 char *fmt =
423 "================================================\n"
424 "%s\n"
425 "================================================";
426 char *str;
427 int ret;
428 int len;
429
430 assert (c);
431 assert (c->magic == IPMICONSOLE_CTX_MAGIC);
432 assert (buf);
433 assert (buflen);
434 assert (hdr);
435 assert (hdrlen);
436
437 if ((ret = ipmi_is_ipmi_1_5_packet (buf, buflen)) < 0)
438 {
439 IPMICONSOLE_CTX_DEBUG (c, ("ipmi_is_ipmi_1_5_packet: %s", strerror (errno)));
440 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
441 return (-1);
442 }
443
444 if (ret)
445 str = "= Unexpected IPMI 1.5 Packet =";
446 else
447 {
448 uint8_t payload_type;
449
450 if (ipmi_rmcpplus_calculate_payload_type (buf, buflen, &payload_type) < 0)
451 {
452 IPMICONSOLE_CTX_DEBUG (c, ("ipmi_rmcpplus_calculate_payload_type: %s", strerror (errno)));
453 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
454 return (-1);
455 }
456
457 switch (payload_type)
458 {
459 case IPMI_PAYLOAD_TYPE_SOL:
460 str = "= Unexpected SOL Packet =";
461 break;
462 case IPMI_PAYLOAD_TYPE_IPMI:
463 str = "= Unexpected IPMI 2.0 Packet =";
464 break;
465 case IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_REQUEST:
466 str = "= Unexpected Open Session Request =";
467 break;
468 case IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_RESPONSE:
469 str = "= Unexpected Open Session Response =";
470 break;
471 case IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_1:
472 str = "= Unexpected RAKP Message 1 =";
473 break;
474 case IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_2:
475 str = "= Unexpected RAKP Message 2 =";
476 break;
477 case IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_3:
478 str = "= Unexpected RAKP Message 3 =";
479 break;
480 case IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_4:
481 str = "= Unexpected RAKP Message 4 =";
482 break;
483 default:
484 str = "= Unexpected Packet =";
485 }
486 }
487
488 if ((len = snprintf (hdr, hdrlen, fmt, str)) < 0)
489 {
490 IPMICONSOLE_CTX_DEBUG (c, ("snprintf"));
491 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
492 return (-1);
493 }
494
495 if (len >= hdrlen)
496 {
497 IPMICONSOLE_CTX_DEBUG (c, ("snprintf truncation: len = %d", len));
498 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
499 return (-1);
500 }
501
502 return (len);
503 }
504
505 int
506 ipmiconsole_packet_dump_unknown (ipmiconsole_ctx_t c,
507 const void *buf,
508 unsigned int buflen)
509 {
510 char hdr[IPMICONSOLE_MAX_PACKET_DUMP_HDR_LEN];
511 int fd;
512 int ret;
513
514 assert (c);
515 assert (c->magic == IPMICONSOLE_CTX_MAGIC);
516 assert (buf);
517 assert (buflen);
518
519 if (c->config.debug_flags & IPMICONSOLE_DEBUG_STDOUT)
520 fd = STDOUT_FILENO;
521 else if (c->config.debug_flags & IPMICONSOLE_DEBUG_STDERR)
522 fd = STDERR_FILENO;
523 else if (c->config.debug_flags & IPMICONSOLE_DEBUG_FILE)
524 fd = c->debug.debug_fd;
525 else
526 return (0);
527
528 if (_packet_dump_unknown_hdr (c, buf, buflen, hdr, IPMICONSOLE_MAX_PACKET_DUMP_HDR_LEN) < 0)
529 return (-1);
530
531 if ((ret = ipmi_is_ipmi_1_5_packet (buf, buflen)) < 0)
532 {
533 IPMICONSOLE_CTX_DEBUG (c, ("ipmi_is_ipmi_1_5_packet: %s", strerror (errno)));
534 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
535 return (-1);
536 }
537
538 if (ret)
539 {
540 if (ipmi_dump_lan_packet (fd,
541 c->config.hostname,
542 hdr,
543 NULL,
544 buf,
545 buflen,
546 tmpl_lan_msg_hdr_rs,
547 tmpl_unexpected_data) < 0)
548 {
549 IPMICONSOLE_CTX_DEBUG (c, ("ipmi_dump_lan_packet: %s", strerror (errno)));
550 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
551 return (-1);
552 }
553 }
554 else
555 {
556 if (ipmi_dump_rmcpplus_packet (fd,
557 c->config.hostname,
558 hdr,
559 NULL,
560 c->config.authentication_algorithm,
561 c->config.integrity_algorithm,
562 c->config.confidentiality_algorithm,
563 c->session.integrity_key_ptr,
564 c->session.integrity_key_len,
565 c->session.confidentiality_key_ptr,
566 c->session.confidentiality_key_len,
567 buf,
568 buflen,
569 tmpl_lan_msg_hdr_rs,
570 tmpl_unexpected_data) < 0)
571 {
572 IPMICONSOLE_CTX_DEBUG (c, ("ipmi_dump_rmcpplus_packet: %s", strerror (errno)));
573 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
574 return (-1);
575 }
576 }
577
578 return (0);
579 }
580
581
582 static int
583 _ipmi_1_5_packet_assemble (ipmiconsole_ctx_t c,
584 ipmiconsole_packet_type_t p,
585 uint8_t authentication_type,
586 uint32_t inbound_sequence_number,
587 uint32_t session_id,
588 void *authentication_code_data,
589 unsigned int authentication_code_data_len,
590 uint8_t net_fn,
591 fiid_obj_t obj_cmd_rq,
592 void *buf,
593 unsigned int buflen)
594 {
595 int pkt_len;
596
597 assert (c);
598 assert (c->magic == IPMICONSOLE_CTX_MAGIC);
599 assert (IPMICONSOLE_PACKET_TYPE_REQUEST (p));
600 assert (buf);
601 assert (buflen);
602
603 if (fill_rmcp_hdr_ipmi (c->connection.obj_rmcp_hdr_rq) < 0)
604 {
605 IPMICONSOLE_CTX_DEBUG (c, ("fill_rmcp_hdr_ipmi: p = %d; %s", p, strerror (errno)));
606 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
607 return (-1);
608 }
609
610 if (fill_lan_session_hdr (authentication_type,
611 inbound_sequence_number,
612 session_id,
613 c->connection.obj_lan_session_hdr_rq) < 0)
614 {
615 IPMICONSOLE_CTX_DEBUG (c, ("fill_lan_session_hdr: p = %d; %s", p, strerror (errno)));
616 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
617 return (-1);
618 }
619
620 if (fill_lan_msg_hdr (IPMI_SLAVE_ADDRESS_BMC,
621 net_fn,
622 IPMI_BMC_IPMB_LUN_BMC,
623 c->session.requester_sequence_number,
624 c->connection.obj_lan_msg_hdr_rq) < 0)
625 {
626 IPMICONSOLE_CTX_DEBUG (c, ("fill_lan_msg_hdr: p = %d; %s", p, strerror (errno)));
627 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
628 return (-1);
629 }
630
631 if ((pkt_len = assemble_ipmi_lan_pkt (c->connection.obj_rmcp_hdr_rq,
632 c->connection.obj_lan_session_hdr_rq,
633 c->connection.obj_lan_msg_hdr_rq,
634 obj_cmd_rq,
635 authentication_code_data,
636 authentication_code_data_len,
637 buf,
638 buflen,
639 IPMI_INTERFACE_FLAGS_DEFAULT)) < 0)
640 {
641 IPMICONSOLE_CTX_DEBUG (c, ("assemble_ipmi_lan_pkt: p = %d; %s", p, strerror (errno)));
642 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
643 return (-1);
644 }
645
646 return (pkt_len);
647 }
648
649 static int
650 _ipmi_2_0_packet_assemble (ipmiconsole_ctx_t c,
651 ipmiconsole_packet_type_t p,
652 uint8_t payload_type,
653 uint8_t payload_authenticated,
654 uint8_t payload_encrypted,
655 uint32_t session_id,
656 uint32_t session_sequence_number,
657 void *authentication_code_data,
658 unsigned int authentication_code_data_len,
659 uint8_t net_fn,
660 uint8_t authentication_algorithm,
661 uint8_t integrity_algorithm,
662 uint8_t confidentiality_algorithm,
663 void *integrity_key,
664 unsigned int integrity_key_len,
665 void *confidentiality_key,
666 unsigned int confidentiality_key_len,
667 fiid_obj_t obj_cmd_rq,
668 void *buf,
669 unsigned int buflen)
670 {
671 int pkt_len;
672
673 assert (c);
674 assert (c->magic == IPMICONSOLE_CTX_MAGIC);
675 assert (IPMICONSOLE_PACKET_TYPE_REQUEST (p));
676 assert (buf);
677 assert (buflen);
678
679 if (fill_rmcp_hdr_ipmi (c->connection.obj_rmcp_hdr_rq) < 0)
680 {
681 IPMICONSOLE_CTX_DEBUG (c, ("fill_rmcp_hdr_ipmi: p = %d; %s", p, strerror (errno)));
682 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
683 return (-1);
684 }
685
686 if (fill_rmcpplus_session_hdr (payload_type,
687 payload_authenticated,
688 payload_encrypted,
689 0, /* oem_iana */
690 0, /* oem_payload_id */
691 session_id,
692 session_sequence_number,
693 c->connection.obj_rmcpplus_session_hdr_rq) < 0)
694 {
695 IPMICONSOLE_CTX_DEBUG (c, ("fill_rmcpplus_session_hdr: p = %d; %s", p, strerror (errno)));
696 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
697 return (-1);
698 }
699
700 if (fill_lan_msg_hdr (IPMI_SLAVE_ADDRESS_BMC,
701 net_fn,
702 IPMI_BMC_IPMB_LUN_BMC,
703 c->session.requester_sequence_number,
704 c->connection.obj_lan_msg_hdr_rq) < 0)
705 {
706 IPMICONSOLE_CTX_DEBUG (c, ("fill_lan_msg_hdr: p = %d; %s", p, strerror (errno)));
707 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
708 return (-1);
709 }
710
711 if (fill_rmcpplus_session_trlr (c->connection.obj_rmcpplus_session_trlr_rq) < 0)
712 {
713 IPMICONSOLE_CTX_DEBUG (c, ("fill_rmcpplus_session_trlr: p = %d; %s", p, strerror (errno)));
714 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
715 return (-1);
716 }
717
718 if ((pkt_len = assemble_ipmi_rmcpplus_pkt (authentication_algorithm,
719 integrity_algorithm,
720 confidentiality_algorithm,
721 integrity_key,
722 integrity_key_len,
723 confidentiality_key,
724 confidentiality_key_len,
725 authentication_code_data,
726 authentication_code_data_len,
727 c->connection.obj_rmcp_hdr_rq,
728 c->connection.obj_rmcpplus_session_hdr_rq,
729 c->connection.obj_lan_msg_hdr_rq,
730 obj_cmd_rq,
731 c->connection.obj_rmcpplus_session_trlr_rq,
732 buf,
733 buflen,
734 IPMI_INTERFACE_FLAGS_DEFAULT)) < 0)
735 {
736 IPMICONSOLE_CTX_DEBUG (c, ("assemble_ipmi_rmcpplus_pkt: p = %d; %s", p, strerror (errno)));
737 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
738 return (-1);
739 }
740
741 return (pkt_len);
742 }
743
744
745 int
746 ipmiconsole_ipmi_packet_assemble (ipmiconsole_ctx_t c,
747 ipmiconsole_packet_type_t p,
748 void *buf,
749 unsigned int buflen)
750 {
751 char username_buf[IPMI_MAX_USER_NAME_LENGTH+1];
752 char *username = NULL;
753 unsigned int username_len;
754 char *password = NULL;
755 unsigned int password_len;
756 uint8_t authentication_type = 0;
757 uint32_t session_id = 0;
758 uint32_t managed_system_session_id = 0;
759 uint32_t session_sequence_number = 0;
760 uint8_t net_fn = 0;
761 uint8_t payload_type = 0;
762 uint8_t authentication_algorithm = 0;
763 uint8_t integrity_algorithm = 0;
764 void *integrity_key = NULL;
765 unsigned int integrity_key_len = 0;
766 uint8_t confidentiality_algorithm = 0;
767 void *confidentiality_key = NULL;
768 unsigned int confidentiality_key_len = 0;
769 uint8_t payload_authenticated = 0;
770 uint8_t payload_encrypted = 0;
771 fiid_obj_t obj_cmd_rq = NULL;
772 int pkt_len;
773 uint64_t val;
774
775 assert (c);
776 assert (c->magic == IPMICONSOLE_CTX_MAGIC);
777 assert (IPMICONSOLE_PACKET_TYPE_REQUEST (p));
778 assert (p != IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RQ);
779 assert (buf);
780 assert (buflen);
781
782 /* Determine Username */
783 /* IPMI Workaround
784 *
785 * Intel IPMI 2.0 implementations pad their usernames.
786 */
787 if (c->config.workaround_flags & IPMICONSOLE_WORKAROUND_INTEL_2_0_SESSION
788 && p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1)
789 {
790 memset (username_buf, '\0', IPMI_MAX_USER_NAME_LENGTH+1);
791 if (strlen (c->config.username))
792 strcpy (username_buf, c->config.username);
793 username = username_buf;
794 username_len = IPMI_MAX_USER_NAME_LENGTH;
795 }
796 else
797 {
798 if (strlen (c->config.username))
799 username = c->config.username;
800 else
801 username = NULL;
802 username_len = (username) ? strlen (username) : 0;
803 }
804
805 /* Determine Password */
806 if (p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RQ)
807 password = NULL;
808 else
809 {
810 if (strlen (c->config.password))
811 password = c->config.password;
812 else
813 password = NULL;
814 }
815
816 password_len = (password) ? strlen (password) : 0;
817
818 /* IPMI Workaround
819 *
820 * Intel IPMI 2.0 implementations improperly calculate HMAC-MD5-128 hashes
821 * when the passwords are > 16 bytes long. The BMCs probably assume
822 * all keys are <= 16 bytes in length. So we have to adjust.
823 */
824 if (c->config.workaround_flags & IPMICONSOLE_WORKAROUND_INTEL_2_0_SESSION
825 && c->config.authentication_algorithm == IPMI_AUTHENTICATION_ALGORITHM_RAKP_HMAC_MD5
826 && password_len > IPMI_1_5_MAX_PASSWORD_LENGTH)
827 password_len = IPMI_1_5_MAX_PASSWORD_LENGTH;
828
829 /* Determine Authentication Type */
830 if (p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RQ)
831 authentication_type = IPMI_AUTHENTICATION_TYPE_NONE;
832
833 /* Determine Session ID */
834 if (p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RQ
835 || p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_REQUEST
836 || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1
837 || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_3)
838 session_id = 0;
839 else
840 {
841 if (FIID_OBJ_GET (c->connection.obj_open_session_response,
842 "managed_system_session_id",
843 &val) < 0)
844 {
845 IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_get: 'managed_system_session_id': %s",
846 fiid_obj_errormsg (c->connection.obj_open_session_response)));
847 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
848 return (-1);
849 }
850 session_id = val;
851 }
852
853 /* Determine Managed System Session ID */
854 if (p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1
855 || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_3)
856 {
857 if (FIID_OBJ_GET (c->connection.obj_open_session_response,
858 "managed_system_session_id",
859 &val) < 0)
860 {
861 IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_get: 'managed_system_session_id': %s",
862 fiid_obj_errormsg (c->connection.obj_open_session_response)));
863 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
864 return (-1);
865 }
866 managed_system_session_id = val;
867 }
868
869 /* Determine Sequence Number */
870 if (p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RQ
871 || p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_REQUEST
872 || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1
873 || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_3)
874 session_sequence_number = 0;
875 else
876 session_sequence_number = c->session.session_sequence_number;
877
878 /* Determine Network Function */
879 if (p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RQ
880 || p == IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RQ
881 || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RQ
882 || p == IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RQ
883 || p == IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RQ
884 || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RQ
885 || p == IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RQ
886 || p == IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RQ)
887 net_fn = IPMI_NET_FN_APP_RQ;
888
889 /* Determine Payload Type */
890 if (p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_REQUEST)
891 payload_type = IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_REQUEST;
892 else if (p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1)
893 payload_type = IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_1;
894 else if (p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_3)
895 payload_type = IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_3;
896 else if (p == IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RQ
897 || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RQ
898 || p == IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RQ
899 || p == IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RQ
900 || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RQ
901 || p == IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RQ
902 || p == IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RQ)
903 payload_type = IPMI_PAYLOAD_TYPE_IPMI;
904 else if (p == IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RQ)
905 payload_type = IPMI_PAYLOAD_TYPE_SOL;
906
907 /* Determine Authentication/Integrity/Confidentiality Keys */
908 if (p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_REQUEST
909 || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1
910 || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_3)
911 {
912 authentication_algorithm = IPMI_AUTHENTICATION_ALGORITHM_RAKP_NONE;
913 integrity_algorithm = IPMI_INTEGRITY_ALGORITHM_NONE;
914 confidentiality_algorithm = IPMI_CONFIDENTIALITY_ALGORITHM_NONE;
915 integrity_key = NULL;
916 integrity_key_len = 0;
917 confidentiality_key = NULL;
918 confidentiality_key_len = 0;
919 }
920 else
921 {
922 authentication_algorithm = c->config.authentication_algorithm;
923 integrity_algorithm = c->config.integrity_algorithm;
924 confidentiality_algorithm = c->config.confidentiality_algorithm;
925 integrity_key = c->session.integrity_key_ptr;
926 integrity_key_len = c->session.integrity_key_len;
927 confidentiality_key = c->session.confidentiality_key_ptr;
928 confidentiality_key_len = c->session.confidentiality_key_len;
929 }
930
931 /* Determine Payload Authenticated Flag */
932 if (p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_REQUEST
933 || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1
934 || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_3
935 || integrity_algorithm == IPMI_INTEGRITY_ALGORITHM_NONE)
936 payload_authenticated = IPMI_PAYLOAD_FLAG_UNAUTHENTICATED;
937 else
938 payload_authenticated = IPMI_PAYLOAD_FLAG_AUTHENTICATED;
939
940 /* Determine Payload Encrypted Flag */
941 if (p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_REQUEST
942 || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1
943 || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_3
944 || confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_NONE)
945 payload_encrypted = IPMI_PAYLOAD_FLAG_UNENCRYPTED;
946 else
947 payload_encrypted = IPMI_PAYLOAD_FLAG_ENCRYPTED;
948
949 /* Fill/Determine Object */
950
951 if (p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RQ)
952 {
953 if (fill_cmd_get_channel_authentication_capabilities (IPMI_CHANNEL_NUMBER_CURRENT_CHANNEL,
954 c->config.privilege_level,
955 IPMI_GET_IPMI_V20_EXTENDED_DATA,
956 c->connection.obj_authentication_capabilities_rq) < 0)
957 {
958 IPMICONSOLE_CTX_DEBUG (c, ("fill_cmd_get_channel_authentication_capabilities: p = %d; %s", p, strerror (errno)));
959 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
960 return (-1);
961 }
962 obj_cmd_rq = c->connection.obj_authentication_capabilities_rq;
963 }
964 else if (p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_REQUEST)
965 {
966 uint8_t privilege_level;
967
968 /*
969 * IPMI Workaround (achu)
970 *
971 * Forgotten Motherboard
972 *
973 * Cipher suite IDs are attached to specific privilege levels
974 * rather than a maximum privilege level limit. So you can only
975 * authenticate at the configured privilege level rather than a
976 * privilege level <= to it.
977 *
978 * To deal with this situation. We send the "request highest
979 * privilege" flag in the open session request. This should be
980 * enough to work around this issue but still work with other
981 * motherboards.
982 */
983
984 /* IPMI Workaround (achu)
985 *
986 * Discovered on SE7520AF2 with Intel Server Management Module
987 * (Professional Edition)
988 *
989 * The Intel's return IPMI_PRIVILEGE_LEVEL_HIGHEST_LEVEL instead
990 * of an actual privilege, so have to pass the actual privilege
991 * we want to use.
992 */
993
994 /* IPMI Workaround (achu)
995 *
996 * Discovered on Sun Fire 4100, Inventec 5441/Dell Xanadu II,
997 * Supermicro X8DTH, Supermicro X8DTG, Supermicro X8DTU, Intel
998 * S5500WBV/Penguin Relion 700
999 *
1000 * The remote BMC incorrectly calculates keys using the privilege
1001 * specified in the open session stage rather than the privilege
1002 * used during the RAKP1 stage. This can be problematic if you
1003 * specify IPMI_PRIVILEGE_LEVEL_HIGHEST_LEVEL during that stage
1004 * instead of a real privilege level. So we must pass the actual
1005 * privilege we want to use.
1006 */
1007 if (c->config.workaround_flags & IPMICONSOLE_WORKAROUND_INTEL_2_0_SESSION
1008 || c->config.workaround_flags & IPMICONSOLE_WORKAROUND_SUN_2_0_SESSION
1009 || c->config.workaround_flags & IPMICONSOLE_WORKAROUND_OPEN_SESSION_PRIVILEGE)
1010 privilege_level = c->config.privilege_level;
1011 else
1012 privilege_level = IPMI_PRIVILEGE_LEVEL_HIGHEST_LEVEL;
1013
1014 if (fill_rmcpplus_open_session (c->session.message_tag,
1015 privilege_level,
1016 c->session.remote_console_session_id,
1017 c->config.authentication_algorithm,
1018 c->config.integrity_algorithm,
1019 c->config.confidentiality_algorithm,
1020 c->connection.obj_open_session_request) < 0)
1021 {
1022 IPMICONSOLE_CTX_DEBUG (c, ("fill_rmcpplus_open_session: p = %d; %s", p, strerror (errno)));
1023 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1024 return (-1);
1025 }
1026 obj_cmd_rq = c->connection.obj_open_session_request;
1027 }
1028 else if (p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1)
1029 {
1030 if (fill_rmcpplus_rakp_message_1 (c->session.message_tag,
1031 managed_system_session_id,
1032 c->session.remote_console_random_number,
1033 IPMI_REMOTE_CONSOLE_RANDOM_NUMBER_LENGTH,
1034 c->config.privilege_level,
1035 c->session.name_only_lookup,
1036 username,
1037 username_len,
1038 c->connection.obj_rakp_message_1) < 0)
1039 {
1040 IPMICONSOLE_CTX_DEBUG (c, ("fill_rmcpplus_rakp_message_1: p = %d; %s", p, strerror (errno)));
1041 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1042 return (-1);
1043 }
1044 obj_cmd_rq = c->connection.obj_rakp_message_1;
1045 }
1046 else if (p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_3)
1047 {
1048 uint8_t managed_system_random_number[IPMI_MANAGED_SYSTEM_RANDOM_NUMBER_LENGTH];
1049 int managed_system_random_number_len;
1050 uint8_t key_exchange_authentication_code[IPMI_MAX_KEY_EXCHANGE_AUTHENTICATION_CODE_LENGTH];
1051 int key_exchange_authentication_code_len;
1052 uint8_t name_only_lookup;
1053
1054 /* IPMI Workaround
1055 *
1056 * Intel IPMI 2.0 implementations use this flag incorrectly.
1057 */
1058 if (c->config.workaround_flags & IPMICONSOLE_WORKAROUND_INTEL_2_0_SESSION)
1059 name_only_lookup = IPMI_USER_NAME_PRIVILEGE_LOOKUP;
1060 else
1061 name_only_lookup = c->session.name_only_lookup;
1062
1063 if ((managed_system_random_number_len = fiid_obj_get_data (c->connection.obj_rakp_message_2,
1064 "managed_system_random_number",
1065 managed_system_random_number,
1066 IPMI_MANAGED_SYSTEM_RANDOM_NUMBER_LENGTH)) < 0)
1067 {
1068 IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_get_data: 'managed_system_random_number': %s",
1069 fiid_obj_errormsg (c->connection.obj_rakp_message_2)));
1070 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1071 return (-1);
1072 }
1073
1074 if (managed_system_random_number_len != IPMI_MANAGED_SYSTEM_RANDOM_NUMBER_LENGTH)
1075 {
1076 IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_get_data: invalid managed system random number length: %d", managed_system_random_number_len));
1077 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1078 return (-1);
1079 }
1080
1081 if ((key_exchange_authentication_code_len = ipmi_calculate_rakp_3_key_exchange_authentication_code (c->config.authentication_algorithm,
1082 password,
1083 password_len,
1084 managed_system_random_number,
1085 managed_system_random_number_len,
1086 c->session.remote_console_session_id,
1087 name_only_lookup,
1088 c->config.privilege_level,
1089 username,
1090 username_len,
1091 key_exchange_authentication_code,
1092 IPMI_MAX_KEY_EXCHANGE_AUTHENTICATION_CODE_LENGTH)) < 0)
1093 {
1094 IPMICONSOLE_CTX_DEBUG (c, ("ipmi_calculate_rakp_3_key_exchange_authentication_code: p = %d; %s", p, strerror (errno)));
1095 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1096 return (-1);
1097 }
1098
1099 if (fill_rmcpplus_rakp_message_3 (c->session.message_tag,
1100 RMCPPLUS_STATUS_NO_ERRORS,
1101 managed_system_session_id,
1102 key_exchange_authentication_code,
1103 key_exchange_authentication_code_len,
1104 c->connection.obj_rakp_message_3) < 0)
1105 {
1106 IPMICONSOLE_CTX_DEBUG (c, ("fill_rmcpplus_rakp_message_3: p = %d; %s", p, strerror (errno)));
1107 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1108 return (-1);
1109 }
1110 obj_cmd_rq = c->connection.obj_rakp_message_3;
1111 }
1112 else if (p == IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RQ)
1113 {
1114 if (fill_cmd_set_session_privilege_level (c->config.privilege_level,
1115 c->connection.obj_set_session_privilege_level_rq) < 0)
1116 {
1117 IPMICONSOLE_CTX_DEBUG (c, ("fill_cmd_set_session_privilege_level: p = %d; %s", p, strerror (errno)));
1118 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1119 return (-1);
1120 }
1121 obj_cmd_rq = c->connection.obj_set_session_privilege_level_rq;
1122 }
1123 else if (p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RQ)
1124 {
1125 if (fill_cmd_get_channel_payload_support (IPMI_CHANNEL_NUMBER_CURRENT_CHANNEL,
1126 c->connection.obj_get_channel_payload_support_rq) < 0)
1127 {
1128 IPMICONSOLE_CTX_DEBUG (c, ("fill_cmd_get_channel_payload_support: p = %d; %s", p, strerror (errno)));
1129 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1130 return (-1);
1131 }
1132 obj_cmd_rq = c->connection.obj_get_channel_payload_support_rq;
1133 }
1134 else if (p == IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RQ)
1135 {
1136 if (fill_cmd_get_payload_activation_status (IPMI_PAYLOAD_TYPE_SOL,
1137 c->connection.obj_get_payload_activation_status_rq) < 0)
1138 {
1139 IPMICONSOLE_CTX_DEBUG (c, ("fill_cmd_get_payload_activation_status: p = %d; %s", p, strerror (errno)));
1140 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1141 return (-1);
1142 }
1143 obj_cmd_rq = c->connection.obj_get_payload_activation_status_rq;
1144 }
1145 else if (p == IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RQ)
1146 {
1147 uint8_t sol_startup_handshake;
1148 uint8_t authentication_activation;
1149 uint8_t encryption_activation;
1150 uint8_t shared_serial_alert_behavior;
1151
1152 /* IPMI Workaround
1153 *
1154 * Intel IPMI 2.0 specific issue. I have no idea why this is.
1155 * I took it from ipmiutil. Ipmiutil author Andrew Cress cannot
1156 * remember why this is the case either.
1157 */
1158 if (c->config.workaround_flags & IPMICONSOLE_WORKAROUND_INTEL_2_0_SESSION)
1159 sol_startup_handshake = IPMI_SOL_STARTUP_HANDSHAKE_CTS_AND_DCD_SDR_ASSERTED;
1160 else
1161 sol_startup_handshake = IPMI_SOL_STARTUP_HANDSHAKE_CTS_AND_DCD_SDR_DEASSERTED;
1162
1163 if (c->config.integrity_algorithm == IPMI_INTEGRITY_ALGORITHM_NONE)
1164 authentication_activation = IPMI_ACTIVATE_PAYLOAD_WITHOUT_AUTHENTICATION;
1165 else
1166 authentication_activation = IPMI_ACTIVATE_PAYLOAD_WITH_AUTHENTICATION;
1167
1168 if (c->config.confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_NONE)
1169 encryption_activation = IPMI_ACTIVATE_PAYLOAD_WITHOUT_ENCRYPTION;
1170 else
1171 encryption_activation = IPMI_ACTIVATE_PAYLOAD_WITH_ENCRYPTION;
1172
1173 /* Workaround
1174 *
1175 * Discovered on Intel Windmill/Quanta Winterfell/Wiwynn Windmill
1176 *
1177 * Nodes like this to be set, I have no idea why. The boards
1178 * don't even have serial ports.
1179 */
1180 if (c->config.workaround_flags & IPMICONSOLE_WORKAROUND_SERIAL_ALERTS_DEFERRED)
1181 shared_serial_alert_behavior = IPMI_SERIAL_MODEM_ALERTS_DEFERRED_WHILE_SOL_ACTIVE;
1182 else
1183 shared_serial_alert_behavior = IPMI_SERIAL_MODEM_ALERTS_FAIL_WHILE_SOL_ACTIVE;
1184
1185 if (fill_cmd_activate_payload_sol (IPMI_PAYLOAD_TYPE_SOL,
1186 (uint8_t)c->config.sol_payload_instance,
1187 sol_startup_handshake,
1188 shared_serial_alert_behavior,
1189 IPMI_TEST_MODE_DEACTIVATED,
1190 authentication_activation,
1191 encryption_activation,
1192 c->connection.obj_activate_payload_rq) < 0)
1193 {
1194 IPMICONSOLE_CTX_DEBUG (c, ("fill_cmd_activate_payload_sol: p = %d; %s", p, strerror (errno)));
1195 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1196 return (-1);
1197 }
1198 obj_cmd_rq = c->connection.obj_activate_payload_rq;
1199 }
1200 else if (p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RQ)
1201 {
1202 assert (c->session.protocol_state == IPMICONSOLE_PROTOCOL_STATE_SOL_SESSION);
1203
1204 if (fill_cmd_get_channel_payload_version (IPMI_CHANNEL_NUMBER_CURRENT_CHANNEL,
1205 IPMI_PAYLOAD_TYPE_SOL,
1206 c->connection.obj_get_channel_payload_version_rq) < 0)
1207 {
1208 IPMICONSOLE_CTX_DEBUG (c, ("fill_cmd_get_channel_payload_version: p = %d; %s", p, strerror (errno)));
1209 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1210 return (-1);
1211 }
1212 obj_cmd_rq = c->connection.obj_get_channel_payload_version_rq;
1213 }
1214 else if (p == IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RQ)
1215 {
1216 uint8_t payload_instance;
1217
1218 if (c->session.deactivate_payload_instances)
1219 payload_instance = c->session.sol_instances_activated[c->session.sol_instances_deactivated_count];
1220 else
1221 payload_instance = (uint8_t)c->config.sol_payload_instance;
1222
1223 if (fill_cmd_deactivate_payload (IPMI_PAYLOAD_TYPE_SOL,
1224 payload_instance,
1225 0, /* achu: IPMI SPEC says: 0h for SOL */
1226 c->connection.obj_deactivate_payload_rq) < 0)
1227 {
1228 IPMICONSOLE_CTX_DEBUG (c, ("fill_cmd_deactivate_payload: p = %d; %s", p, strerror (errno)));
1229 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1230 return (-1);
1231 }
1232 obj_cmd_rq = c->connection.obj_deactivate_payload_rq;
1233 }
1234 else /* p == IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RQ */
1235 {
1236 if (fill_cmd_close_session (session_id,
1237 NULL,
1238 c->connection.obj_close_session_rq) < 0)
1239 {
1240 IPMICONSOLE_CTX_DEBUG (c, ("fill_cmd_close_session: p = %d; %s", p, strerror (errno)));
1241 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1242 return (-1);
1243 }
1244 obj_cmd_rq = c->connection.obj_close_session_rq;
1245 }
1246
1247 /* IPMI 1.5 Style Packets */
1248 if (p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RQ)
1249 {
1250 if ((pkt_len = _ipmi_1_5_packet_assemble (c,
1251 p,
1252 authentication_type,
1253 session_sequence_number,
1254 session_id,
1255 password,
1256 password_len,
1257 net_fn,
1258 obj_cmd_rq,
1259 buf,
1260 buflen)) < 0)
1261 return (-1);
1262 }
1263 else /* IPMI 2.0 Style Packets */
1264 {
1265 if ((pkt_len = _ipmi_2_0_packet_assemble (c,
1266 p,
1267 payload_type,
1268 payload_authenticated,
1269 payload_encrypted,
1270 session_id,
1271 session_sequence_number,
1272 password,
1273 password_len,
1274 net_fn,
1275 authentication_algorithm,
1276 integrity_algorithm,
1277 confidentiality_algorithm,
1278 integrity_key,
1279 integrity_key_len,
1280 confidentiality_key,
1281 confidentiality_key_len,
1282 obj_cmd_rq,
1283 buf,
1284 buflen)) < 0)
1285 return (-1);
1286 }
1287
1288 return (pkt_len);
1289 }
1290
1291 int
1292 ipmiconsole_sol_packet_assemble (ipmiconsole_ctx_t c,
1293 uint8_t packet_sequence_number,
1294 uint8_t packet_ack_nack_sequence_number,
1295 uint8_t accepted_character_count,
1296 uint8_t generate_break,
1297 void *character_data,
1298 unsigned int character_data_len,
1299 void *buf,
1300 unsigned int buflen)
1301 {
1302 char *password = NULL;
1303 uint32_t session_id = 0;
1304 uint8_t payload_authenticated = 0;
1305 uint8_t payload_encrypted = 0;
1306 uint8_t ack;
1307 int pkt_len;
1308 uint64_t val;
1309 int rv = -1;
1310
1311 assert (c);
1312 assert (c->magic == IPMICONSOLE_CTX_MAGIC);
1313 assert (c->session.protocol_state == IPMICONSOLE_PROTOCOL_STATE_SOL_SESSION);
1314 assert (character_data_len <= c->session.max_sol_character_send_size);
1315
1316 /* If the packet sequence number is 0, that means this is an ACK
1317 * only packet. So the ack_nack sequence number should be non-zero
1318 * and no character data should be sent. The accepted character
1319 * count can be 0 to indicate a NACK instead of an ACK.
1320 */
1321 assert (packet_sequence_number
1322 || (!packet_sequence_number
1323 && packet_ack_nack_sequence_number
1324 && !character_data_len));
1325 assert (buf);
1326 assert (buflen);
1327
1328 if (strlen (c->config.password))
1329 password = c->config.password;
1330 else
1331 password = NULL;
1332
1333 if (FIID_OBJ_GET (c->connection.obj_open_session_response,
1334 "managed_system_session_id",
1335 &val) < 0)
1336 {
1337 IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_get: 'managed_system_session_id': %s",
1338 fiid_obj_errormsg (c->connection.obj_open_session_response)));
1339 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1340 goto cleanup;
1341 }
1342 session_id = val;
1343
1344 /* Determine Payload Authenticated Flag */
1345 if (c->config.integrity_algorithm == IPMI_INTEGRITY_ALGORITHM_NONE)
1346 payload_authenticated = IPMI_PAYLOAD_FLAG_UNAUTHENTICATED;
1347 else
1348 payload_authenticated = IPMI_PAYLOAD_FLAG_AUTHENTICATED;
1349
1350 /* Determine Payload Encrypted Flag */
1351 if (c->config.confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_NONE)
1352 payload_encrypted = IPMI_PAYLOAD_FLAG_UNENCRYPTED;
1353 else
1354 payload_encrypted = IPMI_PAYLOAD_FLAG_ENCRYPTED;
1355
1356 /* Determine ACK flag */
1357 if (!packet_sequence_number)
1358 {
1359 if (accepted_character_count)
1360 ack = IPMI_SOL_ACK;
1361 else
1362 ack = IPMI_SOL_NACK;
1363 }
1364 else
1365 /* XXX: Hopefully this is right. Specification is unclear */
1366 ack = 0;
1367
1368 /* Fill/Determine Object */
1369 if (fill_sol_payload_data_remote_console_to_bmc (packet_sequence_number,
1370 packet_ack_nack_sequence_number,
1371 accepted_character_count,
1372 0,
1373 0,
1374 0,
1375 0,
1376 generate_break,
1377 0,
1378 ack,
1379 character_data,
1380 character_data_len,
1381 c->connection.obj_sol_payload_data_rq) < 0)
1382 {
1383 IPMICONSOLE_CTX_DEBUG (c, ("fill_sol_payload_data_remote_console_to_bmc: %s", strerror (errno)));
1384 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1385 goto cleanup;
1386 }
1387
1388 if ((pkt_len = _ipmi_2_0_packet_assemble (c,
1389 IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RQ,
1390 IPMI_PAYLOAD_TYPE_SOL,
1391 payload_authenticated,
1392 payload_encrypted,
1393 session_id,
1394 c->session.session_sequence_number,
1395 password,
1396 (password) ? strlen (password) : 0,
1397 0,
1398 c->config.authentication_algorithm,
1399 c->config.integrity_algorithm,
1400 c->config.confidentiality_algorithm,
1401 c->session.integrity_key_ptr,
1402 c->session.integrity_key_len,
1403 c->session.confidentiality_key_ptr,
1404 c->session.confidentiality_key_len,
1405 c->connection.obj_sol_payload_data_rq,
1406 buf,
1407 buflen)) < 0)
1408 goto cleanup;
1409
1410 rv = pkt_len;
1411 cleanup:
1412 return (rv);
1413 }
1414
1415
1416 int
1417 ipmiconsole_packet_unassemble (ipmiconsole_ctx_t c,
1418 ipmiconsole_packet_type_t *p,
1419 const void *buf,
1420 unsigned int buflen)
1421 {
1422 ipmiconsole_packet_type_t pkt;
1423 fiid_obj_t obj_cmd = NULL;
1424 int ret, pkt_ret = 0;
1425
1426 assert (c);
1427 assert (c->magic == IPMICONSOLE_CTX_MAGIC);
1428 assert (p);
1429 assert (buf);
1430 assert (buflen);
1431
1432 /* Calculate packet type */
1433
1434 if ((ret = ipmi_is_ipmi_1_5_packet (buf, buflen)) < 0)
1435 {
1436 IPMICONSOLE_CTX_DEBUG (c, ("ipmi_is_ipmi_1_5_packet: %s", strerror (errno)));
1437 /* Assume malformed packet */
1438 pkt_ret = 0;
1439 goto out;
1440 }
1441
1442 if (ret)
1443 {
1444 if (c->session.protocol_state == IPMICONSOLE_PROTOCOL_STATE_GET_AUTHENTICATION_CAPABILITIES_SENT)
1445 pkt = IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RS;
1446 else
1447 {
1448 /* Unexpected packet, throw it away */
1449 IPMICONSOLE_CTX_DEBUG (c, ("Unexpected IPMI 1.5 Packet: protocol_state = %d", c->session.protocol_state));
1450 pkt_ret = 0;
1451 goto out;
1452 }
1453
1454 obj_cmd = ipmiconsole_packet_object (c, pkt);
1455
1456 if ((pkt_ret = unassemble_ipmi_lan_pkt (buf,
1457 buflen,
1458 c->connection.obj_rmcp_hdr_rs,
1459 c->connection.obj_lan_session_hdr_rs,
1460 c->connection.obj_lan_msg_hdr_rs,
1461 obj_cmd,
1462 c->connection.obj_lan_msg_trlr_rs,
1463 IPMI_INTERFACE_FLAGS_DEFAULT)) < 0)
1464 {
1465 IPMICONSOLE_CTX_DEBUG (c, ("unassemble_ipmi_lan_pkt: %s", strerror (errno)));
1466 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1467 return (-1);
1468 }
1469 *p = pkt;
1470 }
1471 else
1472 {
1473 uint8_t payload_type;
1474
1475 if (ipmi_rmcpplus_calculate_payload_type (buf, buflen, &payload_type) < 0)
1476 {
1477 IPMICONSOLE_CTX_DEBUG (c, ("ipmi_rmcpplus_calculate_payload_type: %s", strerror (errno)));
1478 /* Assume malformed packet */
1479 pkt_ret = 0;
1480 goto out;
1481 }
1482
1483 if (payload_type == IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_RESPONSE
1484 || payload_type == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_2
1485 || payload_type == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_4)
1486 {
1487 if (c->session.protocol_state == IPMICONSOLE_PROTOCOL_STATE_OPEN_SESSION_REQUEST_SENT)
1488 pkt = IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_RESPONSE;
1489 else if (c->session.protocol_state == IPMICONSOLE_PROTOCOL_STATE_RAKP_MESSAGE_1_SENT)
1490 pkt = IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_2;
1491 else if (c->session.protocol_state == IPMICONSOLE_PROTOCOL_STATE_RAKP_MESSAGE_3_SENT)
1492 pkt = IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_4;
1493 else
1494 {
1495 IPMICONSOLE_CTX_DEBUG (c, ("Unexpected IPMI 2.0 Session Setup Packet: protocol_state = %d", c->session.protocol_state));
1496 pkt_ret = 0;
1497 goto out;
1498 }
1499
1500 obj_cmd = ipmiconsole_packet_object (c, pkt);
1501
1502 /* IPMI 2.0 Pre-Session Establishment Packets */
1503 if ((pkt_ret = unassemble_ipmi_rmcpplus_pkt (IPMI_AUTHENTICATION_ALGORITHM_RAKP_NONE,
1504 IPMI_INTEGRITY_ALGORITHM_NONE,
1505 IPMI_CONFIDENTIALITY_ALGORITHM_NONE,
1506 NULL,
1507 0,
1508 NULL,
1509 0,
1510 buf,
1511 buflen,
1512 c->connection.obj_rmcp_hdr_rs,
1513 c->connection.obj_rmcpplus_session_hdr_rs,
1514 c->connection.obj_rmcpplus_payload_rs,
1515 c->connection.obj_lan_msg_hdr_rs,
1516 obj_cmd,
1517 c->connection.obj_lan_msg_trlr_rs,
1518 c->connection.obj_rmcpplus_session_trlr_rs,
1519 IPMI_INTERFACE_FLAGS_DEFAULT)) < 0)
1520 {
1521 IPMICONSOLE_CTX_DEBUG (c, ("unassemble_ipmi_rmcpplus_pkt: %s", strerror (errno)));
1522 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1523 return (-1);
1524 }
1525 *p = pkt;
1526 }
1527 else if (payload_type == IPMI_PAYLOAD_TYPE_IPMI
1528 || payload_type == IPMI_PAYLOAD_TYPE_SOL)
1529 {
1530 if (payload_type == IPMI_PAYLOAD_TYPE_IPMI)
1531 {
1532 if (c->session.protocol_state == IPMICONSOLE_PROTOCOL_STATE_SET_SESSION_PRIVILEGE_LEVEL_SENT)
1533 pkt = IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS;
1534 else if (c->session.protocol_state == IPMICONSOLE_PROTOCOL_STATE_GET_CHANNEL_PAYLOAD_SUPPORT_SENT)
1535 pkt = IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RS;
1536 else if (c->session.protocol_state == IPMICONSOLE_PROTOCOL_STATE_GET_PAYLOAD_ACTIVATION_STATUS_SENT)
1537 pkt = IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RS;
1538 else if (c->session.protocol_state == IPMICONSOLE_PROTOCOL_STATE_ACTIVATE_PAYLOAD_SENT)
1539 pkt = IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS;
1540 else if (c->session.protocol_state == IPMICONSOLE_PROTOCOL_STATE_SOL_SESSION)
1541 pkt = IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RS;
1542 else if (c->session.protocol_state == IPMICONSOLE_PROTOCOL_STATE_DEACTIVATE_PAYLOAD_SENT)
1543 pkt = IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RS;
1544 else if (c->session.protocol_state == IPMICONSOLE_PROTOCOL_STATE_CLOSE_SESSION_SENT)
1545 pkt = IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RS;
1546 else
1547 {
1548 IPMICONSOLE_CTX_DEBUG (c, ("Unexpected IPMI 2.0 IPMI Packet: protocol_state = %d", c->session.protocol_state));
1549 pkt_ret = 0;
1550 goto out;
1551 }
1552 }
1553 else
1554 {
1555 if (c->session.protocol_state != IPMICONSOLE_PROTOCOL_STATE_SOL_SESSION)
1556 {
1557 IPMICONSOLE_CTX_DEBUG (c, ("Unexpected IPMI 2.0 SOL Packet: protocol_state = %d", c->session.protocol_state));
1558 pkt_ret = 0;
1559 goto out;
1560 }
1561 pkt = IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RS;
1562 }
1563
1564 obj_cmd = ipmiconsole_packet_object (c, pkt);
1565
1566 /* IPMI 2.0 Session Packets */
1567 if ((pkt_ret = unassemble_ipmi_rmcpplus_pkt (c->config.authentication_algorithm,
1568 c->config.integrity_algorithm,
1569 c->config.confidentiality_algorithm,
1570 c->session.integrity_key_ptr,
1571 c->session.integrity_key_len,
1572 c->session.confidentiality_key_ptr,
1573 c->session.confidentiality_key_len,
1574 buf,
1575 buflen,
1576 c->connection.obj_rmcp_hdr_rs,
1577 c->connection.obj_rmcpplus_session_hdr_rs,
1578 c->connection.obj_rmcpplus_payload_rs,
1579 c->connection.obj_lan_msg_hdr_rs,
1580 obj_cmd,
1581 c->connection.obj_lan_msg_trlr_rs,
1582 c->connection.obj_rmcpplus_session_trlr_rs,
1583 IPMI_INTERFACE_FLAGS_DEFAULT)) < 0)
1584 {
1585 IPMICONSOLE_CTX_DEBUG (c, ("unassemble_ipmi_rmcpplus_pkt: %s", strerror (errno)));
1586 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1587 return (-1);
1588 }
1589 *p = pkt;
1590 }
1591 else
1592 {
1593 IPMICONSOLE_CTX_DEBUG (c, ("Unexpected payload_type: payload_type = %u", payload_type));
1594 pkt_ret = 0;
1595 goto out;
1596 }
1597 }
1598
1599 out:
1600 return (pkt_ret);
1601 }
1602
1603 int
1604 ipmiconsole_calculate_errnum (ipmiconsole_ctx_t c,
1605 ipmiconsole_packet_type_t p)
1606 {
1607 fiid_obj_t obj_cmd;
1608 uint64_t val;
1609
1610 assert (c);
1611 assert (c->magic == IPMICONSOLE_CTX_MAGIC);
1612 assert (IPMICONSOLE_PACKET_TYPE_RESPONSE (p));
1613
1614 if (!(obj_cmd = ipmiconsole_packet_object (c, p)))
1615 return (-1);
1616
1617 if (p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_RESPONSE
1618 || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_2
1619 || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_4)
1620 {
1621 uint8_t rmcpplus_status_code;
1622
1623 if (FIID_OBJ_GET (obj_cmd, "rmcpplus_status_code", &val) < 0)
1624 {
1625 IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_get: 'rmcpplus_status_code': %s",
1626 fiid_obj_errormsg (obj_cmd)));
1627 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1628 return (-1);
1629 }
1630 rmcpplus_status_code = val;
1631
1632 if (rmcpplus_status_code == RMCPPLUS_STATUS_NO_ERRORS)
1633 {
1634 IPMICONSOLE_CTX_DEBUG (c, ("called with valid success code; p = %d", p));
1635 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1636 return (-1);
1637 }
1638 else if (rmcpplus_status_code == RMCPPLUS_STATUS_INSUFFICIENT_RESOURCES_TO_CREATE_A_SESSION
1639 || rmcpplus_status_code == RMCPPLUS_STATUS_INSUFFICIENT_RESOURCES_TO_CREATE_A_SESSION_AT_THE_REQUESTED_TIME)
1640 {
1641 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_BMC_BUSY);
1642 return (0);
1643 }
1644 else if (rmcpplus_status_code == RMCPPLUS_STATUS_UNAUTHORIZED_ROLE_OR_PRIVILEGE_LEVEL_REQUESTED
1645 || rmcpplus_status_code == RMCPPLUS_STATUS_INVALID_ROLE)
1646 {
1647 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_PRIVILEGE_LEVEL_CANNOT_BE_OBTAINED);
1648 return (0);
1649 }
1650 else if (rmcpplus_status_code == RMCPPLUS_STATUS_UNAUTHORIZED_NAME)
1651 {
1652 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_USERNAME_INVALID);
1653 return (0);
1654 }
1655 else if (rmcpplus_status_code == RMCPPLUS_STATUS_NO_CIPHER_SUITE_MATCH_WITH_PROPOSED_SECURITY_ALGORITHMS)
1656 {
1657 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_CIPHER_SUITE_ID_UNAVAILABLE);
1658 return (0);
1659 }
1660 else if (rmcpplus_status_code == RMCPPLUS_STATUS_INVALID_INTEGRITY_CHECK_VALUE)
1661 {
1662 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_PASSWORD_INVALID);
1663 return (0);
1664 }
1665 }
1666 else
1667 {
1668 uint8_t comp_code;
1669
1670 if (FIID_OBJ_GET (obj_cmd, "comp_code", &val) < 0)
1671 {
1672 IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_get: 'comp_code': %s",
1673 fiid_obj_errormsg (obj_cmd)));
1674 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1675 return (-1);
1676 }
1677 comp_code = val;
1678
1679 if (comp_code == IPMI_COMP_CODE_COMMAND_SUCCESS)
1680 {
1681 IPMICONSOLE_CTX_DEBUG (c, ("called with valid success code; p = %d", p));
1682 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1683 return (-1);
1684 }
1685
1686 if (p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RS
1687 && comp_code == IPMI_COMP_CODE_INVALID_DATA_FIELD_IN_REQUEST)
1688 {
1689 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_IPMI_2_0_UNAVAILABLE);
1690 return (0);
1691 }
1692 else if (p == IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS
1693 && (comp_code == IPMI_COMP_CODE_ACTIVATE_PAYLOAD_PAYLOAD_ALREADY_ACTIVE_ON_ANOTHER_SESSION
1694 || comp_code == IPMI_COMP_CODE_ACTIVATE_PAYLOAD_PAYLOAD_ACTIVATION_LIMIT_REACHED))
1695 {
1696 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SOL_INUSE);
1697 return (0);
1698 }
1699 else if (p == IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS
1700 && comp_code == IPMI_COMP_CODE_ACTIVATE_PAYLOAD_CANNOT_ACTIVATE_PAYLOAD_WITH_ENCRYPTION)
1701 {
1702 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SOL_REQUIRES_NO_ENCRYPTION);
1703 return (0);
1704 }
1705 /* Workaround
1706 *
1707 * Inventec 5441/Dell Xanadu II returns
1708 * IPMI_COMP_CODE_PARAMETER_OUT_OF_RANGE, so we'll assume that
1709 * return code always means we need encryption.
1710 */
1711 else if (p == IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS
1712 && (comp_code == IPMI_COMP_CODE_ACTIVATE_PAYLOAD_CANNOT_ACTIVATE_PAYLOAD_WITHOUT_ENCRYPTION
1713 || comp_code == IPMI_COMP_CODE_PARAMETER_OUT_OF_RANGE))
1714 {
1715 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SOL_REQUIRES_ENCRYPTION);
1716 return (0);
1717 }
1718 else if (p == IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS
1719 && comp_code == IPMI_COMP_CODE_ACTIVATE_PAYLOAD_PAYLOAD_TYPE_IS_DISABLED)
1720 {
1721 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SOL_UNAVAILABLE);
1722 return (0);
1723 }
1724 else if (p == IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS
1725 && (comp_code == IPMI_COMP_CODE_SET_SESSION_PRIVILEGE_LEVEL_REQUESTED_LEVEL_NOT_AVAILABLE_FOR_USER
1726 || comp_code == IPMI_COMP_CODE_SET_SESSION_PRIVILEGE_LEVEL_REQUESTED_LEVEL_EXCEEDS_USER_PRIVILEGE_LIMIT))
1727 {
1728 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_PRIVILEGE_LEVEL_CANNOT_BE_OBTAINED);
1729 return (0);
1730 }
1731
1732 if (comp_code == IPMI_COMP_CODE_INSUFFICIENT_PRIVILEGE_LEVEL)
1733 {
1734 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_PRIVILEGE_LEVEL_INSUFFICIENT);
1735 return (0);
1736 }
1737
1738 }
1739
1740 ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_BMC_ERROR);
1741 return (0);
1742 }
1743