1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <libipmi.h> 29 #include <string.h> 30 31 #include "ipmi_impl.h" 32 33 /* 34 * Get User Access. See section 22.27. 35 * 36 * See libipmi.h for a complete description of IPMI reference material. 37 */ 38 39 typedef struct ipmi_get_user_access_req { 40 DECL_BITFIELD2( 41 igua_channel :4, 42 __reserved1 :4); 43 DECL_BITFIELD2( 44 igua_uid :2, 45 __reserved2 :6); 46 } ipmi_get_user_access_req_t; 47 48 #define IPMI_CMD_GET_USER_ACCESS 0x44 49 50 typedef struct ipmi_get_user_access { 51 DECL_BITFIELD2( 52 igua_max_uid :4, 53 __reserved1 :4); 54 DECL_BITFIELD2( 55 igua_enable_status :4, 56 igua_enabled_uid :4); 57 DECL_BITFIELD2( 58 __reserved2 :4, 59 igua_fixed_uid :4); 60 DECL_BITFIELD5( 61 __reserved3 :1, 62 igua_only_callback :1, 63 igua_link_auth_enable :1, 64 igua_ipmi_msg_enable :1, 65 igua_privilege_level :4); 66 } ipmi_get_user_access_t; 67 68 #define IPMI_USER_ENABLE_UNSPECIFIED 0x00 69 #define IPMI_USER_ENABLE_SETPASSWD 0x01 70 #define IPMI_USER_DISABLE_SETPASSWD 0x02 71 72 #define IPMI_USER_CHANNEL_CURRENT 0xe 73 74 /* 75 * Get User Name. See section 22.29 76 */ 77 78 #define IPMI_CMD_GET_USER_NAME 0x46 79 80 /* 81 * Set User Password. See section 22.30 82 */ 83 84 #define IPMI_CMD_SET_USER_PASSWORD 0x47 85 86 typedef struct ipmi_set_user_password { 87 DECL_BITFIELD3( 88 isup_uid :6, 89 __reserved1 :1, 90 isup_len20 :1); 91 DECL_BITFIELD2( 92 isup_op :2, 93 __reserved2 :6); 94 char isup_passwd[20]; 95 } ipmi_set_user_password_t; 96 97 #define IPMI_PASSWORD_OP_DISABLE 0x0 98 #define IPMI_PASSWORD_OP_ENABLE 0x1 99 #define IPMI_PASSWORD_OP_SET 0x2 100 #define IPMI_PASSWORD_OP_TEST 0x3 101 102 static ipmi_get_user_access_t * 103 ipmi_get_user_access(ipmi_handle_t *ihp, uint8_t channel, uint8_t uid) 104 { 105 ipmi_cmd_t cmd, *resp; 106 ipmi_get_user_access_req_t req = { 0 }; 107 108 req.igua_channel = channel; 109 req.igua_uid = uid; 110 111 cmd.ic_netfn = IPMI_NETFN_APP; 112 cmd.ic_cmd = IPMI_CMD_GET_USER_ACCESS; 113 cmd.ic_lun = 0; 114 cmd.ic_data = &req; 115 cmd.ic_dlen = sizeof (req); 116 117 if ((resp = ipmi_send(ihp, &cmd)) == NULL) { 118 /* 119 * If sessions aren't supported on the current channel, some 120 * service processors (notably Sun's ILOM) will return an 121 * invalid request completion code (0xCC). For these SPs, we 122 * translate this to the more appropriate EIPMI_INVALID_COMMAND. 123 */ 124 if (ipmi_errno(ihp) == EIPMI_INVALID_REQUEST) 125 (void) ipmi_set_error(ihp, EIPMI_INVALID_COMMAND, 126 NULL); 127 return (NULL); 128 } 129 130 if (resp->ic_dlen < sizeof (ipmi_get_user_access_t)) { 131 (void) ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL); 132 return (NULL); 133 } 134 135 return (resp->ic_data); 136 } 137 138 static const char * 139 ipmi_get_user_name(ipmi_handle_t *ihp, uint8_t uid) 140 { 141 ipmi_cmd_t cmd, *resp; 142 143 cmd.ic_netfn = IPMI_NETFN_APP; 144 cmd.ic_cmd = IPMI_CMD_GET_USER_ACCESS; 145 cmd.ic_lun = 0; 146 cmd.ic_data = &uid; 147 cmd.ic_dlen = sizeof (uid); 148 149 if ((resp = ipmi_send(ihp, &cmd)) == NULL) 150 return (NULL); 151 152 if (resp->ic_dlen < 16) { 153 (void) ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL); 154 return (NULL); 155 } 156 157 return (resp->ic_data); 158 } 159 160 void 161 ipmi_user_clear(ipmi_handle_t *ihp) 162 { 163 ipmi_user_t *up, *next; 164 165 while ((up = ihp->ih_users) != NULL) { 166 next = up->iu_next; 167 ipmi_free(ihp, up->iu_name); 168 ipmi_free(ihp, up); 169 ihp->ih_users = next; 170 } 171 } 172 173 /* 174 * Returns user information in a well-defined structure. 175 */ 176 int 177 ipmi_user_iter(ipmi_handle_t *ihp, int (*func)(ipmi_user_t *, void *), 178 void *data) 179 { 180 ipmi_get_user_access_t *resp; 181 uint8_t i; 182 ipmi_user_t *up; 183 const char *name; 184 185 ipmi_user_clear(ihp); 186 187 /* 188 * First get the number of active users on the system by requesting the 189 * reserved user ID (0). 190 */ 191 if ((resp = ipmi_get_user_access(ihp, 192 IPMI_USER_CHANNEL_CURRENT, 0)) == NULL) 193 return (-1); 194 195 for (i = 1; i <= resp->igua_max_uid; i++) { 196 if ((resp = ipmi_get_user_access(ihp, 197 IPMI_USER_CHANNEL_CURRENT, i)) == NULL) 198 return (-1); 199 200 if ((up = ipmi_zalloc(ihp, sizeof (ipmi_user_t))) == NULL) 201 return (-1); 202 203 up->iu_enabled = resp->igua_enabled_uid; 204 up->iu_uid = i; 205 up->iu_ipmi_msg_enable = resp->igua_ipmi_msg_enable; 206 up->iu_link_auth_enable = resp->igua_link_auth_enable; 207 up->iu_priv = resp->igua_privilege_level; 208 up->iu_next = ihp->ih_users; 209 ihp->ih_users = up; 210 211 if ((name = ipmi_get_user_name(ihp, i)) == NULL) 212 return (-1); 213 214 if (*name != '\0' && 215 (up->iu_name = ipmi_strdup(ihp, name)) == NULL) 216 return (-1); 217 } 218 219 for (up = ihp->ih_users; up != NULL; up = up->iu_next) { 220 if (func(up, data) != 0) 221 return (-1); 222 } 223 224 return (0); 225 } 226 227 typedef struct ipmi_user_cb { 228 const char *uic_name; 229 uint8_t uic_uid; 230 ipmi_user_t *uic_result; 231 } ipmi_user_cb_t; 232 233 static int 234 ipmi_user_callback(ipmi_user_t *up, void *data) 235 { 236 ipmi_user_cb_t *cbp = data; 237 238 if (cbp->uic_result != NULL) 239 return (0); 240 241 if (up->iu_name) { 242 if (strcmp(up->iu_name, cbp->uic_name) == 0) 243 cbp->uic_result = up; 244 } else if (up->iu_uid == cbp->uic_uid) { 245 cbp->uic_result = up; 246 } 247 248 return (0); 249 } 250 251 ipmi_user_t * 252 ipmi_user_lookup_name(ipmi_handle_t *ihp, const char *name) 253 { 254 ipmi_user_cb_t cb = { 0 }; 255 256 cb.uic_name = name; 257 cb.uic_result = NULL; 258 259 if (ipmi_user_iter(ihp, ipmi_user_callback, &cb) != 0) 260 return (NULL); 261 262 if (cb.uic_result == NULL) 263 (void) ipmi_set_error(ihp, EIPMI_NOT_PRESENT, 264 "no such user"); 265 266 return (cb.uic_result); 267 } 268 269 ipmi_user_t * 270 ipmi_user_lookup_id(ipmi_handle_t *ihp, uint8_t uid) 271 { 272 ipmi_user_cb_t cb = { 0 }; 273 274 cb.uic_uid = uid; 275 cb.uic_result = NULL; 276 277 if (ipmi_user_iter(ihp, ipmi_user_callback, &cb) != 0) 278 return (NULL); 279 280 if (cb.uic_result == NULL) 281 (void) ipmi_set_error(ihp, EIPMI_NOT_PRESENT, 282 "no such user"); 283 284 return (cb.uic_result); 285 } 286 287 int 288 ipmi_user_set_password(ipmi_handle_t *ihp, uint8_t uid, const char *passwd) 289 { 290 ipmi_set_user_password_t req = { 0 }; 291 ipmi_cmd_t cmd; 292 293 req.isup_uid = uid; 294 req.isup_op = IPMI_PASSWORD_OP_SET; 295 296 if (strlen(passwd) > 19) 297 return (ipmi_set_error(ihp, EIPMI_INVALID_REQUEST, 298 "password length must be less than 20 characters")); 299 300 if (strlen(passwd) > 15) 301 req.isup_len20 = 1; 302 303 (void) strcpy(req.isup_passwd, passwd); 304 305 cmd.ic_netfn = IPMI_NETFN_APP; 306 cmd.ic_cmd = IPMI_CMD_SET_USER_PASSWORD; 307 cmd.ic_lun = 0; 308 cmd.ic_data = &req; 309 if (req.isup_len20) 310 cmd.ic_dlen = sizeof (req); 311 else 312 cmd.ic_dlen = sizeof (req) - 4; 313 314 if (ipmi_send(ihp, &cmd) == NULL) 315 return (-1); 316 317 return (0); 318 } 319