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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
29 #include "ipmi_impl.h"
31 typedef struct ipmi_user_impl
{
37 * Get User Access. See section 22.27.
39 * See libipmi.h for a complete description of IPMI reference material.
42 typedef struct ipmi_get_user_access_req
{
49 } ipmi_get_user_access_req_t
;
51 #define IPMI_CMD_GET_USER_ACCESS 0x44
53 typedef struct ipmi_get_user_access
{
58 igua_enable_status
:4,
65 igua_only_callback
:1,
66 igua_link_auth_enable
:1,
67 igua_ipmi_msg_enable
:1,
68 igua_privilege_level
:4);
69 } ipmi_get_user_access_t
;
71 #define IPMI_USER_ENABLE_UNSPECIFIED 0x00
72 #define IPMI_USER_ENABLE_SETPASSWD 0x01
73 #define IPMI_USER_DISABLE_SETPASSWD 0x02
75 #define IPMI_USER_CHANNEL_CURRENT 0xe
78 * Get User Name. See section 22.29
81 #define IPMI_CMD_GET_USER_NAME 0x46
84 * Set User Password. See section 22.30
87 #define IPMI_CMD_SET_USER_PASSWORD 0x47
89 typedef struct ipmi_set_user_password
{
98 } ipmi_set_user_password_t
;
100 #define IPMI_PASSWORD_OP_DISABLE 0x0
101 #define IPMI_PASSWORD_OP_ENABLE 0x1
102 #define IPMI_PASSWORD_OP_SET 0x2
103 #define IPMI_PASSWORD_OP_TEST 0x3
105 static ipmi_get_user_access_t
*
106 ipmi_get_user_access(ipmi_handle_t
*ihp
, uint8_t channel
, uint8_t uid
)
108 ipmi_cmd_t cmd
, *resp
;
109 ipmi_get_user_access_req_t req
= { 0 };
111 req
.igua_channel
= channel
;
114 cmd
.ic_netfn
= IPMI_NETFN_APP
;
115 cmd
.ic_cmd
= IPMI_CMD_GET_USER_ACCESS
;
118 cmd
.ic_dlen
= sizeof (req
);
120 if ((resp
= ipmi_send(ihp
, &cmd
)) == NULL
) {
122 * If sessions aren't supported on the current channel, some
123 * service processors (notably Sun's ILOM) will return an
124 * invalid request completion code (0xCC). For these SPs, we
125 * translate this to the more appropriate EIPMI_INVALID_COMMAND.
127 if (ipmi_errno(ihp
) == EIPMI_INVALID_REQUEST
)
128 (void) ipmi_set_error(ihp
, EIPMI_INVALID_COMMAND
,
133 if (resp
->ic_dlen
< sizeof (ipmi_get_user_access_t
)) {
134 (void) ipmi_set_error(ihp
, EIPMI_BAD_RESPONSE_LENGTH
, NULL
);
138 return (resp
->ic_data
);
142 ipmi_get_user_name(ipmi_handle_t
*ihp
, uint8_t uid
)
144 ipmi_cmd_t cmd
, *resp
;
146 cmd
.ic_netfn
= IPMI_NETFN_APP
;
147 cmd
.ic_cmd
= IPMI_CMD_GET_USER_NAME
;
150 cmd
.ic_dlen
= sizeof (uid
);
152 if ((resp
= ipmi_send(ihp
, &cmd
)) == NULL
)
155 if (resp
->ic_dlen
< 16) {
156 (void) ipmi_set_error(ihp
, EIPMI_BAD_RESPONSE_LENGTH
, NULL
);
160 return (resp
->ic_data
);
164 ipmi_user_clear(ipmi_handle_t
*ihp
)
166 ipmi_user_impl_t
*uip
;
168 while ((uip
= ipmi_list_next(&ihp
->ih_users
)) != NULL
) {
169 ipmi_list_delete(&ihp
->ih_users
, uip
);
170 ipmi_free(ihp
, uip
->iu_user
.iu_name
);
176 * Returns user information in a well-defined structure.
179 ipmi_user_iter(ipmi_handle_t
*ihp
, int (*func
)(ipmi_user_t
*, void *),
182 ipmi_get_user_access_t
*resp
;
184 ipmi_user_impl_t
*uip
;
188 ipmi_deviceid_t
*devid
;
190 ipmi_user_clear(ihp
);
192 channel
= IPMI_USER_CHANNEL_CURRENT
;
195 * Get the number of active users on the system by requesting the first
198 if ((resp
= ipmi_get_user_access(ihp
, channel
, 1)) == NULL
) {
200 * Some versions of the Sun ILOM have a bug which prevent the
201 * GET USER ACCESS command from succeeding over the default
202 * channel. If this fails and we are on ILOM, then attempt to
203 * use the standard channel (1) instead.
205 if ((devid
= ipmi_get_deviceid(ihp
)) == NULL
)
208 if (!ipmi_is_sun_ilom(devid
))
212 if ((resp
= ipmi_get_user_access(ihp
, channel
, 1)) == NULL
)
216 uid_max
= resp
->igua_max_uid
;
217 for (i
= 1; i
<= uid_max
; i
++) {
218 if (i
!= 1 && (resp
= ipmi_get_user_access(ihp
,
219 channel
, i
)) == NULL
)
222 if ((uip
= ipmi_zalloc(ihp
, sizeof (ipmi_user_impl_t
))) == NULL
)
227 up
->iu_enabled
= resp
->igua_enabled_uid
;
229 up
->iu_ipmi_msg_enable
= resp
->igua_ipmi_msg_enable
;
230 up
->iu_link_auth_enable
= resp
->igua_link_auth_enable
;
231 up
->iu_priv
= resp
->igua_privilege_level
;
233 ipmi_list_append(&ihp
->ih_users
, uip
);
236 * If we are requesting a username that doesn't have a
237 * supported username, we may get an INVALID REQUEST response.
238 * If this is the case, then continue as if there is no known
241 if ((name
= ipmi_get_user_name(ihp
, i
)) == NULL
) {
242 if (ipmi_errno(ihp
) == EIPMI_INVALID_REQUEST
)
251 if ((up
->iu_name
= ipmi_strdup(ihp
, name
)) == NULL
)
255 for (uip
= ipmi_list_next(&ihp
->ih_users
); uip
!= NULL
;
256 uip
= ipmi_list_next(uip
)) {
257 if (func(&uip
->iu_user
, data
) != 0)
264 typedef struct ipmi_user_cb
{
265 const char *uic_name
;
267 ipmi_user_t
*uic_result
;
271 ipmi_user_callback(ipmi_user_t
*up
, void *data
)
273 ipmi_user_cb_t
*cbp
= data
;
275 if (cbp
->uic_result
!= NULL
)
279 if (strcmp(up
->iu_name
, cbp
->uic_name
) == 0)
280 cbp
->uic_result
= up
;
281 } else if (up
->iu_uid
== cbp
->uic_uid
) {
282 cbp
->uic_result
= up
;
289 ipmi_user_lookup_name(ipmi_handle_t
*ihp
, const char *name
)
291 ipmi_user_cb_t cb
= { 0 };
294 cb
.uic_result
= NULL
;
296 if (ipmi_user_iter(ihp
, ipmi_user_callback
, &cb
) != 0)
299 if (cb
.uic_result
== NULL
)
300 (void) ipmi_set_error(ihp
, EIPMI_NOT_PRESENT
,
303 return (cb
.uic_result
);
307 ipmi_user_lookup_id(ipmi_handle_t
*ihp
, uint8_t uid
)
309 ipmi_user_cb_t cb
= { 0 };
312 cb
.uic_result
= NULL
;
314 if (ipmi_user_iter(ihp
, ipmi_user_callback
, &cb
) != 0)
317 if (cb
.uic_result
== NULL
)
318 (void) ipmi_set_error(ihp
, EIPMI_NOT_PRESENT
,
321 return (cb
.uic_result
);
325 ipmi_user_set_password(ipmi_handle_t
*ihp
, uint8_t uid
, const char *passwd
)
327 ipmi_set_user_password_t req
= { 0 };
331 req
.isup_op
= IPMI_PASSWORD_OP_SET
;
333 if (strlen(passwd
) > 19)
334 return (ipmi_set_error(ihp
, EIPMI_INVALID_REQUEST
,
335 "password length must be less than 20 characters"));
337 if (strlen(passwd
) > 15)
340 (void) strcpy(req
.isup_passwd
, passwd
);
342 cmd
.ic_netfn
= IPMI_NETFN_APP
;
343 cmd
.ic_cmd
= IPMI_CMD_SET_USER_PASSWORD
;
347 cmd
.ic_dlen
= sizeof (req
);
349 cmd
.ic_dlen
= sizeof (req
) - 4;
351 if (ipmi_send(ihp
, &cmd
) == NULL
)