1 /* 2 * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * Redistribution of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * Redistribution in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * Neither the name of Sun Microsystems, Inc. or the names of 16 * contributors may be used to endorse or promote products derived 17 * from this software without specific prior written permission. 18 * 19 * This software is provided "AS IS," without a warranty of any kind. 20 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, 21 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A 22 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. 23 * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE 24 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING 25 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL 26 * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, 27 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR 28 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF 29 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, 30 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 31 */ 32 33 #include <stdlib.h> 34 #include <string.h> 35 #include <stdio.h> 36 #include <sys/types.h> 37 #include <sys/select.h> 38 #include <sys/time.h> 39 #include <signal.h> 40 #include <unistd.h> 41 42 #include <ipmitool/helper.h> 43 #include <ipmitool/log.h> 44 #include <ipmitool/ipmi.h> 45 #include <ipmitool/ipmi_intf.h> 46 #include <ipmitool/ipmi_user.h> 47 #include <ipmitool/ipmi_constants.h> 48 #include <ipmitool/ipmi_strings.h> 49 #include <ipmitool/bswap.h> 50 51 52 extern int verbose; 53 extern int csv_output; 54 55 56 #define IPMI_PASSWORD_DISABLE_USER 0x00 57 #define IPMI_PASSWORD_ENABLE_USER 0x01 58 #define IPMI_PASSWORD_SET_PASSWORD 0x02 59 #define IPMI_PASSWORD_TEST_PASSWORD 0x03 60 61 /* 62 * ipmi_get_user_access 63 * 64 * param intf [in] 65 * param channel_number [in] 66 * param user_id [in] 67 * param user_access [out] 68 * 69 * return 0 on succes 70 * 1 on failure 71 */ 72 static int 73 ipmi_get_user_access( 74 struct ipmi_intf *intf, 75 uint8_t channel_number, 76 uint8_t user_id, 77 struct user_access_rsp *user_access) 78 { 79 struct ipmi_rs * rsp; 80 struct ipmi_rq req; 81 uint8_t msg_data[2]; 82 83 memset(&req, 0, sizeof(req)); 84 req.msg.netfn = IPMI_NETFN_APP; /* 0x06 */ 85 req.msg.cmd = IPMI_GET_USER_ACCESS; /* 0x44 */ 86 req.msg.data = msg_data; 87 req.msg.data_len = 2; 88 89 90 /* The channel number will remain constant throughout this function */ 91 msg_data[0] = channel_number; 92 msg_data[1] = user_id; 93 94 rsp = intf->sendrecv(intf, &req); 95 96 if (rsp == NULL) { 97 lprintf(LOG_ERR, "Get User Access command failed " 98 "(channel %d, user %d)", channel_number, user_id); 99 return -1; 100 } 101 if (rsp->ccode > 0) { 102 lprintf(LOG_ERR, "Get User Access command failed " 103 "(channel %d, user %d): %s", channel_number, user_id, 104 val2str(rsp->ccode, completion_code_vals)); 105 return -1; 106 } 107 108 memcpy(user_access, 109 rsp->data, 110 sizeof(struct user_access_rsp)); 111 112 return 0; 113 } 114 115 116 117 /* 118 * ipmi_get_user_name 119 * 120 * param intf [in] 121 * param channel_number [in] 122 * param user_id [in] 123 * param user_name [out] 124 * 125 * return 0 on succes 126 * 1 on failure 127 */ 128 static int 129 ipmi_get_user_name( 130 struct ipmi_intf *intf, 131 uint8_t user_id, 132 char *user_name) 133 { 134 struct ipmi_rs * rsp; 135 struct ipmi_rq req; 136 uint8_t msg_data[1]; 137 138 memset(user_name, 0, 17); 139 140 memset(&req, 0, sizeof(req)); 141 req.msg.netfn = IPMI_NETFN_APP; /* 0x06 */ 142 req.msg.cmd = IPMI_GET_USER_NAME; /* 0x45 */ 143 req.msg.data = msg_data; 144 req.msg.data_len = 1; 145 146 msg_data[0] = user_id; 147 148 rsp = intf->sendrecv(intf, &req); 149 150 if (rsp == NULL) { 151 lprintf(LOG_ERR, "Get User Name command failed (user %d)", 152 user_id); 153 return -1; 154 } 155 if (rsp->ccode > 0) { 156 if (rsp->ccode == 0xcc) 157 return 0; 158 lprintf(LOG_ERR, "Get User Name command failed (user %d): %s", 159 user_id, val2str(rsp->ccode, completion_code_vals)); 160 return -1; 161 } 162 163 memcpy(user_name, rsp->data, 16); 164 165 return 0; 166 } 167 168 169 170 171 static void 172 dump_user_access( 173 uint8_t user_id, 174 const char * user_name, 175 struct user_access_rsp * user_access) 176 { 177 static int printed_header = 0; 178 179 if (! printed_header) 180 { 181 printf("ID Name Callin Link Auth IPMI Msg " 182 "Channel Priv Limit\n"); 183 printed_header = 1; 184 } 185 186 printf("%-4d%-17s%-8s%-11s%-11s%-s\n", 187 user_id, 188 user_name, 189 user_access->no_callin_access? "false": "true ", 190 user_access->link_auth_access? "true ": "false", 191 user_access->ipmi_messaging_access? "true ": "false", 192 val2str(user_access->channel_privilege_limit, 193 ipmi_privlvl_vals)); 194 } 195 196 197 198 static void 199 dump_user_access_csv( 200 uint8_t user_id, 201 const char *user_name, 202 struct user_access_rsp *user_access) 203 { 204 printf("%d,%s,%s,%s,%s,%s\n", 205 user_id, 206 user_name, 207 user_access->no_callin_access? "false": "true", 208 user_access->link_auth_access? "true": "false", 209 user_access->ipmi_messaging_access? "true": "false", 210 val2str(user_access->channel_privilege_limit, 211 ipmi_privlvl_vals)); 212 } 213 214 static int 215 ipmi_print_user_list( 216 struct ipmi_intf *intf, 217 uint8_t channel_number) 218 { 219 /* This is where you were! */ 220 char user_name[17]; 221 struct user_access_rsp user_access; 222 uint8_t current_user_id = 1; 223 224 225 do 226 { 227 if (ipmi_get_user_access(intf, 228 channel_number, 229 current_user_id, 230 &user_access)) 231 return -1; 232 233 234 if (ipmi_get_user_name(intf, 235 current_user_id, 236 user_name)) 237 return -1; 238 239 if ((current_user_id == 0) || 240 user_access.link_auth_access || 241 user_access.ipmi_messaging_access || 242 strcmp("", user_name)) 243 { 244 if (csv_output) 245 dump_user_access_csv(current_user_id, 246 user_name, &user_access); 247 else 248 dump_user_access(current_user_id, 249 user_name, 250 &user_access); 251 } 252 253 254 ++current_user_id; 255 } while((current_user_id <= user_access.maximum_ids) && 256 (current_user_id <= IPMI_UID_MAX)); /* Absolute maximum allowed by spec */ 257 258 259 return 0; 260 } 261 262 263 264 static int 265 ipmi_print_user_summary( 266 struct ipmi_intf * intf, 267 uint8_t channel_number) 268 { 269 struct user_access_rsp user_access; 270 271 if (ipmi_get_user_access(intf, 272 channel_number, 273 1, 274 &user_access)) 275 return -1; 276 277 if (csv_output) 278 { 279 printf("%d,%d,%d\n", 280 user_access.maximum_ids, 281 user_access.enabled_user_count, 282 user_access.fixed_name_count); 283 } 284 else 285 { 286 printf("Maximum IDs : %d\n", 287 user_access.maximum_ids); 288 printf("Enabled User Count : %d\n", 289 user_access.enabled_user_count); 290 printf("Fixed Name Count : %d\n", 291 user_access.fixed_name_count); 292 } 293 294 return 0; 295 } 296 297 298 299 /* 300 * ipmi_user_set_username 301 */ 302 static int 303 ipmi_user_set_username( 304 struct ipmi_intf *intf, 305 uint8_t user_id, 306 const char *name) 307 { 308 struct ipmi_rs * rsp; 309 struct ipmi_rq req; 310 uint8_t msg_data[17]; 311 312 /* 313 * Ensure there is space for the name in the request message buffer 314 */ 315 if (strlen(name) >= sizeof(msg_data)) { 316 return -1; 317 } 318 319 memset(&req, 0, sizeof(req)); 320 req.msg.netfn = IPMI_NETFN_APP; /* 0x06 */ 321 req.msg.cmd = IPMI_SET_USER_NAME; /* 0x45 */ 322 req.msg.data = msg_data; 323 req.msg.data_len = sizeof(msg_data); 324 memset(msg_data, 0, sizeof(msg_data)); 325 326 /* The channel number will remain constant throughout this function */ 327 msg_data[0] = user_id; 328 strncpy((char *)(msg_data + 1), name, strlen(name)); 329 330 rsp = intf->sendrecv(intf, &req); 331 332 if (rsp == NULL) { 333 lprintf(LOG_ERR, "Set User Name command failed (user %d, name %s)", 334 user_id, name); 335 return -1; 336 } 337 if (rsp->ccode > 0) { 338 lprintf(LOG_ERR, "Set User Name command failed (user %d, name %s): %s", 339 user_id, name, val2str(rsp->ccode, completion_code_vals)); 340 return -1; 341 } 342 343 return 0; 344 } 345 346 static int 347 ipmi_user_set_userpriv( 348 struct ipmi_intf *intf, 349 uint8_t channel, 350 uint8_t user_id, 351 const unsigned char privLevel) 352 { 353 struct ipmi_rs *rsp; 354 struct ipmi_rq req; 355 uint8_t msg_data[4] = {0, 0, 0, 0}; 356 357 memset(&req, 0, sizeof(req)); 358 req.msg.netfn = IPMI_NETFN_APP; /* 0x06 */ 359 req.msg.cmd = IPMI_SET_USER_ACCESS; /* 0x43 */ 360 req.msg.data = msg_data; 361 req.msg.data_len = 4; 362 363 /* The channel number will remain constant throughout this function */ 364 msg_data[0] = (channel & 0x0f); 365 msg_data[1] = (user_id & 0x3f); 366 msg_data[2] = (privLevel & 0x0f); 367 msg_data[3] = 0; 368 369 rsp = intf->sendrecv(intf, &req); 370 371 if (rsp == NULL) 372 { 373 lprintf(LOG_ERR, "Set Privilege Level command failed (user %d)", 374 user_id); 375 return -1; 376 } 377 if (rsp->ccode > 0) 378 { 379 lprintf(LOG_ERR, "Set Privilege Level command failed (user %d): %s", 380 user_id, val2str(rsp->ccode, completion_code_vals)); 381 return -1; 382 } 383 384 return 0; 385 } 386 387 /* 388 * ipmi_user_set_password 389 * 390 * This function is responsible for 4 things 391 * Enabling/Disabling users 392 * Setting/Testing passwords 393 */ 394 static int 395 ipmi_user_set_password( 396 struct ipmi_intf * intf, 397 uint8_t user_id, 398 uint8_t operation, 399 const char *password, 400 int is_twenty_byte_password) 401 { 402 struct ipmi_rs * rsp; 403 struct ipmi_rq req; 404 uint8_t msg_data[22]; 405 406 int password_length = (is_twenty_byte_password? 20 : 16); 407 408 memset(&req, 0, sizeof(req)); 409 req.msg.netfn = IPMI_NETFN_APP; /* 0x06 */ 410 req.msg.cmd = IPMI_SET_USER_PASSWORD; /* 0x47 */ 411 req.msg.data = msg_data; 412 req.msg.data_len = password_length + 2; 413 414 415 /* The channel number will remain constant throughout this function */ 416 msg_data[0] = user_id; 417 418 if (is_twenty_byte_password) 419 msg_data[0] |= 0x80; 420 421 msg_data[1] = operation; 422 423 memset(msg_data + 2, 0, password_length); 424 425 if (password != NULL) 426 strncpy((char *)(msg_data + 2), password, password_length); 427 428 rsp = intf->sendrecv(intf, &req); 429 430 if (rsp == NULL) { 431 lprintf(LOG_ERR, "Set User Password command failed (user %d)", 432 user_id); 433 return -1; 434 } 435 if (rsp->ccode > 0) { 436 lprintf(LOG_ERR, "Set User Password command failed (user %d): %s", 437 user_id, val2str(rsp->ccode, completion_code_vals)); 438 return rsp->ccode; 439 } 440 441 return 0; 442 } 443 444 445 446 /* 447 * ipmi_user_test_password 448 * 449 * Call ipmi_user_set_password, and interpret the result 450 */ 451 static int 452 ipmi_user_test_password( 453 struct ipmi_intf * intf, 454 uint8_t user_id, 455 const char * password, 456 int is_twenty_byte_password) 457 { 458 int ret; 459 460 ret = ipmi_user_set_password(intf, 461 user_id, 462 IPMI_PASSWORD_TEST_PASSWORD, 463 password, 464 is_twenty_byte_password); 465 466 switch (ret) { 467 case 0: 468 printf("Success\n"); 469 break; 470 case 0x80: 471 printf("Failure: password incorrect\n"); 472 break; 473 case 0x81: 474 printf("Failure: wrong password size\n"); 475 break; 476 default: 477 printf("Unknown error\n"); 478 } 479 480 return ((ret == 0) ? 0 : -1); 481 } 482 483 484 /* 485 * print_user_usage 486 */ 487 static void 488 print_user_usage(void) 489 { 490 lprintf(LOG_NOTICE, "User Commands:"); 491 lprintf(LOG_NOTICE, " summary [<channel number>]"); 492 lprintf(LOG_NOTICE, " list [<channel number>]"); 493 lprintf(LOG_NOTICE, " set name <user id> <username>"); 494 lprintf(LOG_NOTICE, " set password <user id> [<password>]"); 495 lprintf(LOG_NOTICE, " disable <user id>"); 496 lprintf(LOG_NOTICE, " enable <user id>"); 497 lprintf(LOG_NOTICE, 498 " priv <user id> <privilege level> [<channel number>]"); 499 lprintf(LOG_NOTICE, " test <user id> <16|20> [<password]>\n"); 500 } 501 502 503 const char * 504 ipmi_user_build_password_prompt(uint8_t user_id) 505 { 506 static char prompt[128]; 507 memset(prompt, 0, 128); 508 snprintf(prompt, 128, "Password for user %d: ", user_id); 509 return prompt; 510 } 511 512 513 /* 514 * ipmi_user_main 515 * 516 * Upon entry to this function argv should contain our arguments 517 * specific to this subcommand 518 */ 519 int 520 ipmi_user_main(struct ipmi_intf * intf, int argc, char ** argv) 521 { 522 int retval = 0; 523 524 /* 525 * Help 526 */ 527 if (argc == 0 || strncmp(argv[0], "help", 4) == 0) 528 { 529 print_user_usage(); 530 } 531 532 /* 533 * Summary 534 */ 535 else if (strncmp(argv[0], "summary", 7) == 0) 536 { 537 uint8_t channel; 538 539 if (argc == 1) 540 channel = 0x0E; /* Ask about the current channel */ 541 else if (argc == 2) 542 { 543 if (str2uchar(argv[1], &channel) != 0) 544 { 545 lprintf(LOG_ERR, "Invalid channel: %s", argv[1]); 546 return (-1); 547 } 548 } 549 else 550 { 551 print_user_usage(); 552 return -1; 553 } 554 555 retval = ipmi_print_user_summary(intf, channel); 556 } 557 558 559 /* 560 * List 561 */ 562 else if (strncmp(argv[0], "list", 4) == 0) 563 { 564 uint8_t channel; 565 566 if (argc == 1) 567 channel = 0x0E; /* Ask about the current channel */ 568 else if (argc == 2) 569 { 570 if (str2uchar(argv[1], &channel) != 0) 571 { 572 lprintf(LOG_ERR, "Invalid channel: %s", argv[1]); 573 return (-1); 574 } 575 } 576 else 577 { 578 print_user_usage(); 579 return -1; 580 } 581 582 retval = ipmi_print_user_list(intf, channel); 583 } 584 585 586 587 /* 588 * Test 589 */ 590 else if (strncmp(argv[0], "test", 4) == 0) 591 { 592 // a little irritating, isn't it 593 if (argc == 3 || argc == 4) 594 { 595 char * password = NULL; 596 int password_length = 0; 597 uint8_t user_id = 0; 598 if (is_ipmi_user_id(argv[1], &user_id)) { 599 return (-1); 600 } 601 if (str2int(argv[2], &password_length) != 0 602 || (password_length != 16 && password_length != 20)) { 603 lprintf(LOG_ERR, 604 "Given password length '%s' is invalid.", 605 argv[2]); 606 lprintf(LOG_ERR, "Expected value is either 16 or 20."); 607 return (-1); 608 } 609 610 if (argc == 3) 611 { 612 /* We need to prompt for a password */ 613 614 char * tmp; 615 const char * password_prompt = 616 ipmi_user_build_password_prompt(user_id); 617 # ifdef HAVE_GETPASSPHRASE 618 tmp = getpassphrase (password_prompt); 619 # else 620 tmp = (char*)getpass (password_prompt); 621 # endif 622 if (tmp != NULL) { 623 password = strdup(tmp); 624 tmp = NULL; 625 } 626 if (password == NULL) { 627 lprintf(LOG_ERR, "ipmitool: malloc failure"); 628 return -1; 629 } 630 } 631 else { 632 password = strdup(argv[3]); 633 } 634 635 636 retval = ipmi_user_test_password(intf, 637 user_id, 638 password, 639 password_length == 20); 640 if (password != NULL) { 641 free(password); 642 password = NULL; 643 } 644 } 645 else 646 { 647 print_user_usage(); 648 return -1; 649 } 650 } 651 652 /* 653 * Set 654 */ 655 else if (strncmp(argv[0], "set", 3) == 0) 656 { 657 /* 658 * Set Password 659 */ 660 if ((argc >= 3) && 661 (strncmp("password", argv[1], 8) == 0)) 662 { 663 char * password = NULL; 664 uint8_t user_id = 0; 665 if (is_ipmi_user_id(argv[2], &user_id)) { 666 return (-1); 667 } 668 669 if (argc == 3) 670 { 671 /* We need to prompt for a password */ 672 char * tmp; 673 const char * password_prompt = 674 ipmi_user_build_password_prompt(user_id); 675 # ifdef HAVE_GETPASSPHRASE 676 tmp = getpassphrase (password_prompt); 677 # else 678 tmp = (char*)getpass (password_prompt); 679 # endif 680 if (tmp != NULL) { 681 password = strdup(tmp); 682 tmp = NULL; 683 } 684 if (password == NULL) { 685 lprintf(LOG_ERR, "ipmitool: malloc failure"); 686 return -1; 687 } 688 # ifdef HAVE_GETPASSPHRASE 689 tmp = getpassphrase (password_prompt); 690 # else 691 tmp = (char*)getpass (password_prompt); 692 # endif 693 if (tmp == NULL) { 694 lprintf(LOG_ERR, "ipmitool: malloc failure"); 695 return (-1); 696 } 697 if (strlen(password) != strlen(tmp) 698 || strncmp(password, tmp, strlen(tmp))) { 699 lprintf(LOG_ERR, "Passwords do not match."); 700 free(password); 701 password = NULL; 702 return -1; 703 } 704 tmp = NULL; 705 } else { 706 password = strdup(argv[3]); 707 } 708 709 if (password == NULL) { 710 lprintf(LOG_ERR, "Unable to parse password argument."); 711 return -1; 712 } 713 else if (strlen(password) > 20) 714 { 715 lprintf(LOG_ERR, "Password is too long (> 20 bytes)"); 716 return -1; 717 } 718 719 retval = ipmi_user_set_password(intf, 720 user_id, 721 IPMI_PASSWORD_SET_PASSWORD, 722 password, 723 strlen(password) > 16); 724 if (password != NULL) { 725 free(password); 726 password = NULL; 727 } 728 } 729 730 /* 731 * Set Name 732 */ 733 else if ((argc >= 2) && 734 (strncmp("name", argv[1], 4) == 0)) 735 { 736 uint8_t user_id = 0; 737 if (argc != 4) 738 { 739 print_user_usage(); 740 return -1; 741 } 742 if (is_ipmi_user_id(argv[2], &user_id)) { 743 return (-1); 744 } 745 746 if (strlen(argv[3]) > 16) 747 { 748 lprintf(LOG_ERR, "Username is too long (> 16 bytes)"); 749 return -1; 750 } 751 752 retval = ipmi_user_set_username(intf, user_id, argv[3]); 753 } 754 else 755 { 756 print_user_usage(); 757 return -1; 758 } 759 } 760 761 else if (strncmp(argv[0], "priv", 4) == 0) 762 { 763 uint8_t user_id; 764 uint8_t priv_level; 765 uint8_t channel = 0x0e; /* Use channel running on */ 766 767 if (argc != 3 && argc != 4) 768 { 769 print_user_usage(); 770 return -1; 771 } 772 773 if (argc == 4) 774 { 775 if (str2uchar(argv[3], &channel) != 0) 776 { 777 lprintf(LOG_ERR, "Invalid channel: %s", argv[3]); 778 return (-1); 779 } 780 channel = (channel & 0x0f); 781 } 782 783 if (str2uchar(argv[2], &priv_level) != 0) 784 { 785 lprintf(LOG_ERR, "Invalid privilege level: %s", argv[2]); 786 return (-1); 787 } 788 priv_level = (priv_level & 0x0f); 789 790 if (is_ipmi_user_id(argv[1], &user_id)) { 791 return (-1); 792 } 793 794 retval = ipmi_user_set_userpriv(intf,channel,user_id,priv_level); 795 } 796 797 /* 798 * Disable / Enable 799 */ 800 else if ((strncmp(argv[0], "disable", 7) == 0) || 801 (strncmp(argv[0], "enable", 6) == 0)) 802 { 803 uint8_t user_id; 804 uint8_t operation; 805 char null_password[16]; /* Not used, but required */ 806 807 memset(null_password, 0, sizeof(null_password)); 808 809 if (argc != 2) 810 { 811 print_user_usage(); 812 return -1; 813 } 814 815 if (is_ipmi_user_id(argv[1], &user_id)) { 816 return (-1); 817 } 818 819 operation = (strncmp(argv[0], "disable", 7) == 0) ? 820 IPMI_PASSWORD_DISABLE_USER : IPMI_PASSWORD_ENABLE_USER; 821 822 retval = ipmi_user_set_password(intf, 823 user_id, 824 operation, 825 null_password, 826 0); /* This field is ignored */ 827 } 828 else 829 { 830 retval = -1; 831 lprintf(LOG_ERR, "Invalid user command: '%s'\n", argv[0]); 832 print_user_usage(); 833 } 834 835 return retval; 836 } 837