sm->expected_failure = 0;
sm->reauthInit = FALSE;
sm->erp_seq = (u32) -1;
+ sm->use_machine_cred = 0;
}
identity_len = config->anonymous_identity_len;
wpa_hexdump_ascii(MSG_DEBUG, "EAP: using anonymous identity",
identity, identity_len);
+ } else if (sm->use_machine_cred) {
+ identity = config->machine_identity;
+ identity_len = config->machine_identity_len;
+ wpa_hexdump_ascii(MSG_DEBUG, "EAP: using machine identity",
+ identity, identity_len);
} else {
identity = config->identity;
identity_len = config->identity_len;
const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len)
{
struct eap_peer_config *config = eap_get_config(sm);
- if (config == NULL)
+
+ if (!config)
return NULL;
+
+ if (sm->use_machine_cred) {
+ *len = config->machine_identity_len;
+ return config->machine_identity;
+ }
+
*len = config->identity_len;
return config->identity;
}
struct eap_peer_config *config)
{
char *name;
+ const u8 *password;
+ size_t password_len;
- if (config->password == NULL)
+ if (sm->use_machine_cred) {
+ password = config->machine_password;
+ password_len = config->machine_password_len;
+ } else {
+ password = config->password;
+ password_len = config->password_len;
+ }
+
+ if (!password)
return -1;
- name = os_zalloc(config->password_len + 1);
- if (name == NULL)
+ name = os_zalloc(password_len + 1);
+ if (!name)
return -1;
- os_memcpy(name, config->password, config->password_len);
+ os_memcpy(name, password, password_len);
ext_password_free(sm->ext_pw_buf);
sm->ext_pw_buf = ext_password_get(sm->ext_pw, name);
const u8 * eap_get_config_password(struct eap_sm *sm, size_t *len)
{
struct eap_peer_config *config = eap_get_config(sm);
- if (config == NULL)
+
+ if (!config)
return NULL;
- if (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
+ if ((sm->use_machine_cred &&
+ (config->flags & EAP_CONFIG_FLAGS_EXT_MACHINE_PASSWORD)) ||
+ (!sm->use_machine_cred &&
+ (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD))) {
if (eap_get_ext_password(sm, config) < 0)
return NULL;
*len = wpabuf_len(sm->ext_pw_buf);
return wpabuf_head(sm->ext_pw_buf);
}
+ if (sm->use_machine_cred) {
+ *len = config->machine_password_len;
+ return config->machine_password;
+ }
+
*len = config->password_len;
return config->password;
}
const u8 * eap_get_config_password2(struct eap_sm *sm, size_t *len, int *hash)
{
struct eap_peer_config *config = eap_get_config(sm);
- if (config == NULL)
+
+ if (!config)
return NULL;
- if (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
+ if ((sm->use_machine_cred &&
+ (config->flags & EAP_CONFIG_FLAGS_EXT_MACHINE_PASSWORD)) ||
+ (!sm->use_machine_cred &&
+ (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD))) {
if (eap_get_ext_password(sm, config) < 0)
return NULL;
if (hash)
return wpabuf_head(sm->ext_pw_buf);
}
+ if (sm->use_machine_cred) {
+ *len = config->machine_password_len;
+ if (hash)
+ *hash = !!(config->flags &
+ EAP_CONFIG_FLAGS_MACHINE_PASSWORD_NTHASH);
+ return config->machine_password;
+ }
+
*len = config->password_len;
if (hash)
*hash = !!(config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH);
u8 *imsi_identity;
size_t imsi_identity_len;
+ /**
+ * machine_identity - EAP Identity for machine credential
+ *
+ * This field is used to set the machine identity or NAI for cases where
+ * and explicit machine credential (instead of or in addition to a user
+ * credential (from %identity) is needed.
+ */
+ u8 *machine_identity;
+
+ /**
+ * machine_identity_len - EAP Identity length for machine credential
+ */
+ size_t machine_identity_len;
+
/**
* password - Password string for EAP
*
*/
size_t password_len;
+ /**
+ * machine_password - Password string for EAP machine credential
+ *
+ * This field is used when machine credential based on username/password
+ * is needed instead of a user credential (from %password). See
+ * %password for more details on the format.
+ */
+ u8 *machine_password;
+
+ /**
+ * machine_password_len - Length of machine credential password field
+ */
+ size_t machine_password_len;
+
/**
* ca_cert - File path to CA certificate file (PEM/DER)
*
#define EAP_CONFIG_FLAGS_PASSWORD_NTHASH BIT(0)
#define EAP_CONFIG_FLAGS_EXT_PASSWORD BIT(1)
+#define EAP_CONFIG_FLAGS_MACHINE_PASSWORD_NTHASH BIT(2)
+#define EAP_CONFIG_FLAGS_EXT_MACHINE_PASSWORD BIT(3)
/**
* flags - Network configuration flags (bitfield)
*
* instead of plaintext password
* bit 1 = password is stored in external storage; the value in the
* password field is the name of that external entry
+ * bit 2 = machine password is represented as a 16-byte NtPasswordHash
+ * value instead of plaintext password
+ * bit 3 = machine password is stored in external storage; the value in
+ * the password field is the name of that external entry
*/
u32 flags;
#ifdef CONFIG_EXT_PASSWORD
if (os_strncmp(value, "ext:", 4) == 0) {
char *name = os_strdup(value + 4);
- if (name == NULL)
+ if (!name)
return -1;
bin_clear_free(ssid->eap.password, ssid->eap.password_len);
ssid->eap.password = (u8 *) name;
size_t res_len;
tmp = wpa_config_parse_string(value, &res_len);
- if (tmp == NULL) {
- wpa_printf(MSG_ERROR, "Line %d: failed to parse "
- "password.", line);
+ if (!tmp) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: failed to parse password.", line);
return -1;
}
wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
/* NtPasswordHash: hash:<32 hex digits> */
if (os_strlen(value + 5) != 2 * 16) {
- wpa_printf(MSG_ERROR, "Line %d: Invalid password hash length "
- "(expected 32 hex digits)", line);
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid password hash length (expected 32 hex digits)",
+ line);
return -1;
}
hash = os_malloc(16);
- if (hash == NULL)
+ if (!hash)
return -1;
if (hexstr2bin(value + 5, hash, 16)) {
}
+static int wpa_config_parse_machine_password(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
+ const char *value)
+{
+ u8 *hash;
+
+ if (os_strcmp(value, "NULL") == 0) {
+ if (!ssid->eap.machine_password)
+ return 1; /* Already unset */
+ wpa_printf(MSG_DEBUG,
+ "Unset configuration string 'machine_password'");
+ bin_clear_free(ssid->eap.machine_password,
+ ssid->eap.machine_password_len);
+ ssid->eap.machine_password = NULL;
+ ssid->eap.machine_password_len = 0;
+ return 0;
+ }
+
+#ifdef CONFIG_EXT_PASSWORD
+ if (os_strncmp(value, "ext:", 4) == 0) {
+ char *name = os_strdup(value + 4);
+
+ if (!name)
+ return -1;
+ bin_clear_free(ssid->eap.machine_password,
+ ssid->eap.machine_password_len);
+ ssid->eap.machine_password = (u8 *) name;
+ ssid->eap.machine_password_len = os_strlen(name);
+ ssid->eap.flags &= ~EAP_CONFIG_FLAGS_MACHINE_PASSWORD_NTHASH;
+ ssid->eap.flags |= EAP_CONFIG_FLAGS_EXT_MACHINE_PASSWORD;
+ return 0;
+ }
+#endif /* CONFIG_EXT_PASSWORD */
+
+ if (os_strncmp(value, "hash:", 5) != 0) {
+ char *tmp;
+ size_t res_len;
+
+ tmp = wpa_config_parse_string(value, &res_len);
+ if (!tmp) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: failed to parse machine_password.",
+ line);
+ return -1;
+ }
+ wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
+ (u8 *) tmp, res_len);
+
+ bin_clear_free(ssid->eap.machine_password,
+ ssid->eap.machine_password_len);
+ ssid->eap.machine_password = (u8 *) tmp;
+ ssid->eap.machine_password_len = res_len;
+ ssid->eap.flags &= ~EAP_CONFIG_FLAGS_MACHINE_PASSWORD_NTHASH;
+ ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_MACHINE_PASSWORD;
+
+ return 0;
+ }
+
+
+ /* NtPasswordHash: hash:<32 hex digits> */
+ if (os_strlen(value + 5) != 2 * 16) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid machine_password hash length (expected 32 hex digits)",
+ line);
+ return -1;
+ }
+
+ hash = os_malloc(16);
+ if (!hash)
+ return -1;
+
+ if (hexstr2bin(value + 5, hash, 16)) {
+ os_free(hash);
+ wpa_printf(MSG_ERROR, "Line %d: Invalid machine_password hash",
+ line);
+ return -1;
+ }
+
+ wpa_hexdump_key(MSG_MSGDUMP, data->name, hash, 16);
+
+ if (ssid->eap.machine_password &&
+ ssid->eap.machine_password_len == 16 &&
+ os_memcmp(ssid->eap.machine_password, hash, 16) == 0 &&
+ (ssid->eap.flags & EAP_CONFIG_FLAGS_MACHINE_PASSWORD_NTHASH)) {
+ bin_clear_free(hash, 16);
+ return 1;
+ }
+ bin_clear_free(ssid->eap.machine_password,
+ ssid->eap.machine_password_len);
+ ssid->eap.machine_password = hash;
+ ssid->eap.machine_password_len = 16;
+ ssid->eap.flags |= EAP_CONFIG_FLAGS_MACHINE_PASSWORD_NTHASH;
+ ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_MACHINE_PASSWORD;
+
+ return 0;
+}
+
+
#ifndef NO_CONFIG_WRITE
+
static char * wpa_config_write_password(const struct parse_data *data,
struct wpa_ssid *ssid)
{
char *buf;
- if (ssid->eap.password == NULL)
+ if (!ssid->eap.password)
return NULL;
#ifdef CONFIG_EXT_PASSWORD
if (ssid->eap.flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
buf = os_zalloc(4 + ssid->eap.password_len + 1);
- if (buf == NULL)
+ if (!buf)
return NULL;
os_memcpy(buf, "ext:", 4);
os_memcpy(buf + 4, ssid->eap.password, ssid->eap.password_len);
}
buf = os_malloc(5 + 32 + 1);
- if (buf == NULL)
+ if (!buf)
return NULL;
os_memcpy(buf, "hash:", 5);
return buf;
}
+
+
+static char * wpa_config_write_machine_password(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ char *buf;
+
+ if (!ssid->eap.machine_password)
+ return NULL;
+
+#ifdef CONFIG_EXT_PASSWORD
+ if (ssid->eap.flags & EAP_CONFIG_FLAGS_EXT_MACHINE_PASSWORD) {
+ buf = os_zalloc(4 + ssid->eap.machine_password_len + 1);
+ if (!buf)
+ return NULL;
+ os_memcpy(buf, "ext:", 4);
+ os_memcpy(buf + 4, ssid->eap.machine_password,
+ ssid->eap.machine_password_len);
+ return buf;
+ }
+#endif /* CONFIG_EXT_PASSWORD */
+
+ if (!(ssid->eap.flags & EAP_CONFIG_FLAGS_MACHINE_PASSWORD_NTHASH)) {
+ return wpa_config_write_string(
+ ssid->eap.machine_password,
+ ssid->eap.machine_password_len);
+ }
+
+ buf = os_malloc(5 + 32 + 1);
+ if (!buf)
+ return NULL;
+
+ os_memcpy(buf, "hash:", 5);
+ wpa_snprintf_hex(buf + 5, 32 + 1, ssid->eap.machine_password, 16);
+
+ return buf;
+}
+
#endif /* NO_CONFIG_WRITE */
#endif /* IEEE8021X_EAPOL */
{ STR_LENe(identity) },
{ STR_LENe(anonymous_identity) },
{ STR_LENe(imsi_identity) },
+ { STR_LENe(machine_identity) },
{ FUNC_KEY(password) },
+ { FUNC_KEY(machine_password) },
{ STRe(ca_cert) },
{ STRe(ca_path) },
{ STRe(client_cert) },
bin_clear_free(eap->identity, eap->identity_len);
os_free(eap->anonymous_identity);
os_free(eap->imsi_identity);
+ os_free(eap->machine_identity);
bin_clear_free(eap->password, eap->password_len);
+ bin_clear_free(eap->machine_password, eap->machine_password_len);
os_free(eap->ca_cert);
os_free(eap->ca_path);
os_free(eap->client_cert);