📄 config.c
字号:
/* * WPA Supplicant / Configuration parser and common functions * Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */#include <stdlib.h>#include <stdio.h>#include <string.h>#include "common.h"#include "wpa.h"#include "sha1.h"#include "wpa_supplicant.h"#include "eapol_sm.h"#include "eap.h"#include "l2_packet.h"#include "config.h"/* * Structure for network configuration parsing. This data is used to implement * a generic parser for each network block variable. The table of configuration * variables is defined below in this file (ssid_fields[]). */struct parse_data { /* Configuration variable name */ char *name; /* Parser function for this variable */ int (*parser)(const struct parse_data *data, struct wpa_ssid *ssid, int line, const char *value); /* Writer function (i.e., to get the variable in text format from * internal presentation). */ char * (*writer)(const struct parse_data *data, struct wpa_ssid *ssid); /* Variable specific parameters for the parser. */ void *param1, *param2, *param3, *param4; /* 0 = this variable can be included in debug output * 1 = this variable contains key/private data and it must not be * included in debug output unless explicitly requested */ int key_data;};static char * wpa_config_parse_string(const char *value, size_t *len){ if (*value == '"') { char *pos; value++; pos = strrchr(value, '"'); if (pos == NULL || pos[1] != '\0') return NULL; *pos = '\0'; *len = strlen(value); return strdup(value); } else { u8 *str; size_t hlen = strlen(value); if (hlen % 1) return NULL; *len = hlen / 2; str = malloc(*len); if (str == NULL) return NULL; if (hexstr2bin(value, str, *len)) { free(str); return NULL; } return (char *) str; }}static int wpa_config_parse_str(const struct parse_data *data, struct wpa_ssid *ssid, int line, const char *value){ size_t res_len, *dst_len; char **dst; dst = (char **) (((u8 *) ssid) + (long) data->param1); dst_len = (size_t *) (((u8 *) ssid) + (long) data->param2); free(*dst); *dst = wpa_config_parse_string(value, &res_len); if (*dst == NULL) { wpa_printf(MSG_ERROR, "Line %d: failed to parse %s '%s'.", line, data->name, data->key_data ? "[KEY DATA REMOVED]" : value); return -1; } if (data->param2) *dst_len = res_len; if (data->key_data) { wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name, (u8 *) *dst, res_len); } else { wpa_hexdump_ascii(MSG_MSGDUMP, data->name, (u8 *) *dst, res_len); } if (data->param3 && res_len < (size_t) data->param3) { wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu " "min_len=%ld)", line, data->name, (unsigned long) res_len, (long) data->param3); free(*dst); *dst = NULL; return -1; } if (data->param4 && res_len > (size_t) data->param4) { wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu " "max_len=%ld)", line, data->name, (unsigned long) res_len, (long) data->param4); free(*dst); *dst = NULL; return -1; } return 0;}static int is_hex(const u8 *data, size_t len){ int i; for (i = 0; i < len; i++) { if (data[i] < 32 || data[i] >= 127) return 1; } return 0;}static char * wpa_config_write_string_ascii(const u8 *value, size_t len){ int i; char *buf, *pos, *end; pos = buf = malloc(len + 3); if (buf == NULL) return NULL; end = buf + len + 3; pos += snprintf(pos, end - pos, "\""); for (i = 0; i < len; i++) pos += snprintf(pos, end - pos, "%c", value[i]); pos += snprintf(pos, end - pos, "\""); return buf;}static char * wpa_config_write_string_hex(const u8 *value, size_t len){ int i; char *buf, *pos, *end; pos = buf = malloc(2 * len + 1); if (buf == NULL) return NULL; memset(buf, 0, 2 * len + 1); end = buf + 2 * len + 1; for (i = 0; i < len; i++) pos += snprintf(pos, end - pos, "%02x", value[i]); return buf;}static char * wpa_config_write_string(const u8 *value, size_t len){ if (value == NULL) return NULL; if (is_hex(value, len)) return wpa_config_write_string_hex(value, len); else return wpa_config_write_string_ascii(value, len);}static char * wpa_config_write_str(const struct parse_data *data, struct wpa_ssid *ssid){ size_t len; char **src; src = (char **) (((u8 *) ssid) + (long) data->param1); if (*src == NULL) return NULL; if (data->param2) len = *((size_t *) (((u8 *) ssid) + (long) data->param2)); else len = strlen(*src); return wpa_config_write_string((const u8 *) *src, len);}static int wpa_config_parse_int(const struct parse_data *data, struct wpa_ssid *ssid, int line, const char *value){ int *dst; dst = (int *) (((u8 *) ssid) + (long) data->param1); *dst = atoi(value); wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst); if (data->param3 && *dst < (long) data->param3) { wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d " "min_value=%ld)", line, data->name, *dst, (long) data->param3); *dst = (long) data->param3; return -1; } if (data->param4 && *dst > (long) data->param4) { wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d " "max_value=%ld)", line, data->name, *dst, (long) data->param4); *dst = (long) data->param4; return -1; } return 0;}static char * wpa_config_write_int(const struct parse_data *data, struct wpa_ssid *ssid){ int *src; char *value; src = (int *) (((u8 *) ssid) + (long) data->param1); value = malloc(20); if (value == NULL) return NULL; snprintf(value, 20, "%d", *src); return value;}static int wpa_config_parse_bssid(const struct parse_data *data, struct wpa_ssid *ssid, int line, const char *value){ if (hwaddr_aton(value, ssid->bssid)) { wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID '%s'.", line, value); return -1; } ssid->bssid_set = 1; wpa_hexdump(MSG_MSGDUMP, "BSSID", ssid->bssid, ETH_ALEN); return 0;}static char * wpa_config_write_bssid(const struct parse_data *data, struct wpa_ssid *ssid){ char *value; if (!ssid->bssid_set) return NULL; value = malloc(20); if (value == NULL) return NULL; snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid)); return value;}static int wpa_config_parse_psk(const struct parse_data *data, struct wpa_ssid *ssid, int line, const char *value){ if (*value == '"') { const char *pos; size_t len; value++; pos = strrchr(value, '"'); if (pos) len = pos - value; else len = strlen(value); if (len < 8 || len > 63) { wpa_printf(MSG_ERROR, "Line %d: Invalid passphrase " "length %lu (expected: 8..63) '%s'.", line, (unsigned long) len, value); return -1; } wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)", (u8 *) value, len); ssid->passphrase = malloc(len + 1); if (ssid->passphrase == NULL) return -1; memcpy(ssid->passphrase, value, len); ssid->passphrase[len] = '\0'; return 0; } if (hexstr2bin(value, ssid->psk, PMK_LEN) || value[PMK_LEN * 2] != '\0') { wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.", line, value); return -1; } ssid->psk_set = 1; wpa_hexdump_key(MSG_MSGDUMP, "PSK", ssid->psk, PMK_LEN); return 0;}static char * wpa_config_write_psk(const struct parse_data *data, struct wpa_ssid *ssid){ if (ssid->passphrase) return wpa_config_write_string_ascii( (const u8 *) ssid->passphrase, strlen(ssid->passphrase)); if (ssid->psk_set) return wpa_config_write_string_hex(ssid->psk, PMK_LEN); return NULL;}static int wpa_config_parse_proto(const struct parse_data *data, struct wpa_ssid *ssid, int line, const char *value){ int val = 0, last, errors = 0; char *start, *end, *buf; buf = strdup(value); if (buf == NULL) return -1; start = buf; while (*start != '\0') { while (*start == ' ' || *start == '\t') start++; if (*start == '\0') break; end = start; while (*end != ' ' && *end != '\t' && *end != '\0') end++; last = *end == '\0'; *end = '\0'; if (strcmp(start, "WPA") == 0) val |= WPA_PROTO_WPA; else if (strcmp(start, "RSN") == 0 || strcmp(start, "WPA2") == 0) val |= WPA_PROTO_RSN; else { wpa_printf(MSG_ERROR, "Line %d: invalid proto '%s'", line, start); errors++; } if (last) break; start = end + 1; } free(buf); if (val == 0) { wpa_printf(MSG_ERROR, "Line %d: no proto values configured.", line); errors++; } wpa_printf(MSG_MSGDUMP, "proto: 0x%x", val); ssid->proto = val; return errors ? -1 : 0;}static char * wpa_config_write_proto(const struct parse_data *data, struct wpa_ssid *ssid){ int first = 1; char *buf, *pos, *end; pos = buf = malloc(10); if (buf == NULL) return NULL; memset(buf, 0, 10); end = buf + 10; if (ssid->proto & WPA_PROTO_WPA) { pos += snprintf(pos, end - pos, "%sWPA", first ? "" : " "); first = 0; } if (ssid->proto & WPA_PROTO_RSN) { pos += snprintf(pos, end - pos, "%sRSN", first ? "" : " "); first = 0; } return buf;}static int wpa_config_parse_key_mgmt(const struct parse_data *data, struct wpa_ssid *ssid, int line, const char *value){ int val = 0, last, errors = 0; char *start, *end, *buf; buf = strdup(value); if (buf == NULL) return -1; start = buf; while (*start != '\0') { while (*start == ' ' || *start == '\t') start++; if (*start == '\0') break; end = start; while (*end != ' ' && *end != '\t' && *end != '\0') end++; last = *end == '\0'; *end = '\0'; if (strcmp(start, "WPA-PSK") == 0) val |= WPA_KEY_MGMT_PSK; else if (strcmp(start, "WPA-EAP") == 0) val |= WPA_KEY_MGMT_IEEE8021X; else if (strcmp(start, "IEEE8021X") == 0) val |= WPA_KEY_MGMT_IEEE8021X_NO_WPA; else if (strcmp(start, "NONE") == 0) val |= WPA_KEY_MGMT_NONE; else if (strcmp(start, "WPA-NONE") == 0) val |= WPA_KEY_MGMT_WPA_NONE; else { wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", line, start); errors++; } if (last) break; start = end + 1; } free(buf); if (val == 0) { wpa_printf(MSG_ERROR, "Line %d: no key_mgmt values configured.", line); errors++; } wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", val); ssid->key_mgmt = val; return errors ? -1 : 0;}static char * wpa_config_write_key_mgmt(const struct parse_data *data, struct wpa_ssid *ssid){ int first = 1; char *buf, *pos, *end; pos = buf = malloc(50); if (buf == NULL) return NULL; memset(buf, 0, 50); end = buf + 50; if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) { pos += snprintf(pos, end - pos, "%sWPA-PSK", first ? "" : " "); first = 0; } if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X) { pos += snprintf(pos, end - pos, "%sWPA-EAP", first ? "" : " "); first = 0; } if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { pos += snprintf(pos, end - pos, "%sIEEE8021X", first ? "" : " "); first = 0; } if (ssid->key_mgmt & WPA_KEY_MGMT_NONE) { pos += snprintf(pos, end - pos, "%sNONE", first ? "" : " "); first = 0; } if (ssid->key_mgmt & WPA_KEY_MGMT_WPA_NONE) { pos += snprintf(pos, end - pos, "%sWPA-NONE", first ? "" : " "); first = 0; } return buf;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -