static char * wpa_config_parse_string(const char *value, size_t *len) { if (*value == '"') { const char *pos; char *str; value++; pos = os_strrchr(value, '"'); if (pos == NULL || pos[1] != '\0') return NULL; *len = pos - value; str = os_malloc(*len + 1); if (str == NULL) return NULL; os_memcpy(str, value, *len); str[*len] = '\0'; return str; } else { u8 *str; size_t tlen, hlen = os_strlen(value); if (hlen & 1) return NULL; tlen = hlen / 2; str = os_malloc(tlen + 1); if (str == NULL) return NULL; if (hexstr2bin(value, str, tlen)) { os_free(str); return NULL; } str[tlen] = '\0'; *len = tlen; return (char *) str; } }
/** * wpa_config_get_line - Read the next configuration file line * @s: Buffer for the line * @size: The buffer length * @stream: File stream to read from * @line: Pointer to a variable storing the file line number * @_pos: Buffer for the pointer to the beginning of data on the text line or * %NULL if not needed (returned value used instead) * Returns: Pointer to the beginning of data on the text line or %NULL if no * more text lines are available. * * This function reads the next non-empty line from the configuration file and * removes comments. The returned string is guaranteed to be null-terminated. */ static char * wpa_config_get_line(char *s, int size, FILE *stream, int *line, char **_pos) { char *pos, *end, *sstart; while (fgets(s, size, stream)) { (*line)++; s[size - 1] = '\0'; if (!newline_terminated(s, size)) { /* * The line was truncated - skip rest of it to avoid * confusing error messages. */ wpa_printf(MSG_INFO, "Long line in configuration file " "truncated"); skip_line_end(stream); } pos = s; /* Skip white space from the beginning of line. */ while (*pos == ' ' || *pos == '\t' || *pos == '\r') pos++; /* Skip comment lines and empty lines */ if (*pos == '#' || *pos == '\n' || *pos == '\0') continue; /* * Remove # comments unless they are within a double quoted * string. */ sstart = os_strchr(pos, '"'); if (sstart) sstart = os_strrchr(sstart + 1, '"'); if (!sstart) sstart = pos; end = os_strchr(sstart, '#'); if (end) *end-- = '\0'; else end = pos + os_strlen(pos) - 1; /* Remove trailing white space. */ while (end > pos && (*end == '\n' || *end == ' ' || *end == '\t' || *end == '\r')) *end-- = '\0'; if (*pos == '\0') continue; if (_pos) *_pos = pos; return pos; } if (_pos) *_pos = NULL; return NULL; }
static int tokenize_cmd(char *cmd, char *argv[]) { char *pos; int argc = 0; pos = cmd; for (;;) { while (*pos == ' ') pos++; if (*pos == '\0') break; argv[argc] = pos; argc++; if (argc == max_args) break; if (*pos == '"') { char *pos2 = os_strrchr(pos, '"'); if (pos2) pos = pos2 + 1; } while (*pos != '\0' && *pos != ' ') pos++; if (*pos == ' ') *pos++ = '\0'; } return argc; }
int linux_br_get(char *brname, const char *ifname) { char path[128], brlink[128], *pos; os_snprintf(path, sizeof(path), "/sys/class/net/%s/brport/bridge", ifname); os_memset(brlink, 0, sizeof(brlink)); #if 0 if (readlink(path, brlink, sizeof(brlink) - 1) < 0) return -1; #else { /*Coverity check - STRING_NULL*/ int len; len = readlink(path, brlink, sizeof(brlink) - 1); if (len < 0 || len >= (int) sizeof(brlink)) { return -1; } brlink[len] = '\0'; } #endif pos = os_strrchr(brlink, '/'); if (pos == NULL) return -1; pos++; os_strlcpy(brname, pos, IFNAMSIZ); return 0; }
/** * wpa_config_get_line - Read the next configuration file line * @s: Buffer for the line * @size: The buffer length * @stream: File stream to read from * @line: Pointer to a variable storing the file line number * @_pos: Buffer for the pointer to the beginning of data on the text line or * %NULL if not needed (returned value used instead) * Returns: Pointer to the beginning of data on the text line or %NULL if no * more text lines are available. * * This function reads the next non-empty line from the configuration file and * removes comments. The returned string is guaranteed to be null-terminated. */ static char * wpa_config_get_line(char *s, int size, FILE *stream, int *line, char **_pos) { char *pos, *end, *sstart; while (fgets(s, size, stream)) { (*line)++; /* Trim trailing whitespace */ pos = s+strlen(s); while (pos > s && !isgraph(pos[-1])) *--pos = '\0'; if (pos == s || s[0] == '#') continue; pos = s; /* Skip white space from the beginning of line. */ while (*pos == ' ' || *pos == '\t') pos++; /* Skip comment lines and empty lines */ if (*pos == '#' || *pos == '\n' || *pos == '\r' || *pos == '\0') continue; /* * Remove # comments unless they are within a double quoted * string. */ sstart = os_strchr(pos, '"'); if (sstart) sstart = os_strrchr(sstart + 1, '"'); if (!sstart) sstart = pos; end = os_strchr(sstart, '#'); if (end) *end-- = '\0'; else end = pos + os_strlen(pos) - 1; /* Remove trailing white space. */ while (end > pos && (*end == '\n' || *end == ' ' || *end == '\t' || *end == '\r')) *end-- = '\0'; if (*pos == '\0') continue; if (_pos) *_pos = pos; return pos; } if (_pos) *_pos = NULL; return NULL; }
static int wpa_config_parse_psk(const struct parse_data *data, struct wpa_ssid *ssid, int line, const char *value) { if (*value == '"') { #ifndef CONFIG_NO_PBKDF2 const char *pos; size_t len; value++; pos = os_strrchr(value, '"'); if (pos) len = pos - value; else len = os_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); if (ssid->passphrase && os_strlen(ssid->passphrase) == len && os_memcmp(ssid->passphrase, value, len) == 0) return 0; ssid->psk_set = 0; os_free(ssid->passphrase); ssid->passphrase = os_malloc(len + 1); if (ssid->passphrase == NULL) return -1; os_memcpy(ssid->passphrase, value, len); ssid->passphrase[len] = '\0'; return 0; #else /* CONFIG_NO_PBKDF2 */ wpa_printf(MSG_ERROR, "Line %d: ASCII passphrase not " "supported.", line); return -1; #endif /* CONFIG_NO_PBKDF2 */ } 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; } os_free(ssid->passphrase); ssid->passphrase = NULL; ssid->psk_set = 1; wpa_hexdump_key(MSG_MSGDUMP, "PSK", ssid->psk, PMK_LEN); return 0; }
int linux_br_get(char *brname, const char *ifname) { char path[128], brlink[128], *pos; os_snprintf(path, sizeof(path), "/sys/class/net/%s/brport/bridge", ifname); os_memset(brlink, 0, sizeof(brlink)); if (readlink(path, brlink, sizeof(brlink) - 1) < 0) return -1; pos = os_strrchr(brlink, '/'); if (pos == NULL) return -1; pos++; os_strlcpy(brname, pos, IFNAMSIZ); return 0; }
char * http_link_update(char *url, const char *base) { char *n; size_t len; const char *pos; /* RFC 2396, Chapter 5.2 */ /* TODO: consider adding all cases described in RFC 2396 */ if (url == NULL) return NULL; if (os_strncmp(url, "http://", 7) == 0) return url; /* absolute link */ if (os_strncmp(base, "http://", 7) != 0) return url; /* unable to handle base URL */ len = os_strlen(url) + 1 + os_strlen(base) + 1; n = os_malloc(len); if (n == NULL) return url; /* failed */ if (url[0] == '/') { pos = os_strchr(base + 7, '/'); if (pos == NULL) { os_snprintf(n, len, "%s%s", base, url); } else { os_memcpy(n, base, pos - base); os_memcpy(n + (pos - base), url, os_strlen(url) + 1); } } else { pos = os_strrchr(base + 7, '/'); if (pos == NULL) { os_snprintf(n, len, "%s/%s", base, url); } else { os_memcpy(n, base, pos - base + 1); os_memcpy(n + (pos - base) + 1, url, os_strlen(url) + 1); } } os_free(url); return n; }
static int hostapd_get_global_ctrl_iface(struct hapd_interfaces *interfaces, const char *path) { char *pos; os_free(interfaces->global_iface_path); interfaces->global_iface_path = os_strdup(path); if (interfaces->global_iface_path == NULL) return -1; pos = os_strrchr(interfaces->global_iface_path, '/'); if (pos == NULL) { os_free(interfaces->global_iface_path); interfaces->global_iface_path = NULL; return -1; } *pos = '\0'; interfaces->global_iface_name = pos + 1; return 0; }
static void wpa_trace_bfd_addr(void *pc) { bfd *abfd = cached_abfd; struct bfd_data data; const char *name; char *aname = NULL; const char *filename; if (abfd == NULL) return; data.pc = (bfd_vma) pc; data.found = FALSE; bfd_map_over_sections(abfd, find_addr_sect, &data); if (!data.found) return; do { if (data.function) aname = bfd_demangle(abfd, data.function, DMGL_ANSI | DMGL_PARAMS); name = aname ? aname : data.function; filename = data.filename; if (filename) { char *end = os_strrchr(filename, '/'); int i = 0; while (*filename && *filename == prg_fname[i] && filename <= end) { filename++; i++; } } wpa_printf(MSG_INFO, " %s() %s:%u", name, filename, data.line); free(aname); data.found = bfd_find_inliner_info(abfd, &data.filename, &data.function, &data.line); } while (data.found); }
int linux_br_get(char *brname, const char *ifname) { char path[128], brlink[128], *pos; ssize_t res; if (!ovs_br_get(brname, ifname)) return 0; os_snprintf(path, sizeof(path), "/sys/class/net/%s/brport/bridge", ifname); res = readlink(path, brlink, sizeof(brlink)); if (res < 0 || (size_t) res >= sizeof(brlink)) return -1; brlink[res] = '\0'; pos = os_strrchr(brlink, '/'); if (pos == NULL) return -1; pos++; os_strlcpy(brname, pos, IFNAMSIZ); return 0; }
static int hostapd_get_global_ctrl_iface(struct hapd_interfaces *interfaces, const char *path) { char *pos; os_free(interfaces->global_iface_path); interfaces->global_iface_path = os_strdup(path); if (interfaces->global_iface_path == NULL) return -1; pos = os_strrchr(interfaces->global_iface_path, '/'); if (pos == NULL) { wpa_printf(MSG_ERROR, "No '/' in the global control interface " "file"); os_free(interfaces->global_iface_path); interfaces->global_iface_path = NULL; return -1; } *pos = '\0'; interfaces->global_iface_name = pos + 1; return 0; }
static void wpa_cli_interactive(void) { #define max_args 10 char cmdbuf[256], *cmd, *argv[max_args], *pos; int argc; #ifdef CONFIG_READLINE char *home, *hfile = NULL; #endif /* CONFIG_READLINE */ printf("\nInteractive mode\n\n"); #ifdef CONFIG_READLINE rl_attempted_completion_function = wpa_cli_completion; home = getenv("HOME"); if (home) { const char *fname = ".wpa_cli_history"; int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1; hfile = os_malloc(hfile_len); if (hfile) { os_snprintf(hfile, hfile_len, "%s/%s", home, fname); hfile[hfile_len - 1] = '\0'; read_history(hfile); stifle_history(100); } } #endif /* CONFIG_READLINE */ do { wpa_cli_recv_pending(monitor_conn, 0, 0); #ifndef CONFIG_NATIVE_WINDOWS alarm(1); #endif /* CONFIG_NATIVE_WINDOWS */ #ifdef CONFIG_READLINE cmd = readline("> "); if (cmd && *cmd) { HIST_ENTRY *h; while (next_history()) ; h = previous_history(); if (h == NULL || os_strcmp(cmd, h->line) != 0) add_history(cmd); next_history(); } #else /* CONFIG_READLINE */ printf("> "); cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin); #endif /* CONFIG_READLINE */ #ifndef CONFIG_NATIVE_WINDOWS alarm(0); #endif /* CONFIG_NATIVE_WINDOWS */ if (cmd == NULL) break; wpa_cli_recv_pending(monitor_conn, 0, 0); pos = cmd; while (*pos != '\0') { if (*pos == '\n') { *pos = '\0'; break; } pos++; } argc = 0; pos = cmd; for (;;) { while (*pos == ' ') pos++; if (*pos == '\0') break; argv[argc] = pos; argc++; if (argc == max_args) break; if (*pos == '"') { char *pos2 = os_strrchr(pos, '"'); if (pos2) pos = pos2 + 1; } while (*pos != '\0' && *pos != ' ') pos++; if (*pos == ' ') *pos++ = '\0'; } if (argc) wpa_request(ctrl_conn, argc, argv); if (cmd != cmdbuf) os_free(cmd); } while (!wpa_cli_quit); #ifdef CONFIG_READLINE if (hfile) { /* Save command history, excluding lines that may contain * passwords. */ HIST_ENTRY *h; history_set_pos(0); h = next_history(); while (h) { char *p = h->line; while (*p == ' ' || *p == '\t') p++; if (os_strncasecmp(p, "pa", 2) == 0 || os_strncasecmp(p, "o", 1) == 0 || os_strncasecmp(p, "n", 1)) { h = remove_history(where_history()); if (h) { os_free(h->line); os_free(h->data); os_free(h); } h = current_history(); } else { h = next_history(); } } write_history(hfile); os_free(hfile); } #endif /* CONFIG_READLINE */ }
static void wpa_cli_reconnect(void) { wpa_cli_close_connection(); ctrl_conn = wpa_cli_open_connection(ctrl_ifname); if (ctrl_conn) { printf("Connection to wpa_supplicant re-established\n"); #ifdef ANDROID if (wpa_ctrl_attach(monitor_conn) == 0) { #else if (wpa_ctrl_attach(ctrl_conn) == 0) { #endif wpa_cli_attached = 1; } else { printf("Warning: Failed to attach to " "wpa_supplicant.\n"); } } } static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read, int action_monitor) { int first = 1; #ifdef ANDROID if (ctrl == NULL) { #else if (ctrl_conn == NULL) { #endif wpa_cli_reconnect(); return; } while (wpa_ctrl_pending(ctrl) > 0) { char buf[256]; size_t len = sizeof(buf) - 1; if (wpa_ctrl_recv(ctrl, buf, &len) == 0) { buf[len] = '\0'; if (action_monitor) wpa_cli_action_process(buf); else { if (in_read && first) printf("\n"); first = 0; printf("%s\n", buf); } } else { printf("Could not read pending message.\n"); break; } } if (wpa_ctrl_pending(ctrl) < 0) { printf("Connection to wpa_supplicant lost - trying to " "reconnect\n"); wpa_cli_reconnect(); } } #ifdef CONFIG_READLINE static char * wpa_cli_cmd_gen(const char *text, int state) { static int i, len; const char *cmd; if (state == 0) { i = 0; len = os_strlen(text); } while ((cmd = wpa_cli_commands[i].cmd)) { i++; if (os_strncasecmp(cmd, text, len) == 0) return os_strdup(cmd); } return NULL; } static char * wpa_cli_dummy_gen(const char *text, int state) { return NULL; } static char ** wpa_cli_completion(const char *text, int start, int end) { return rl_completion_matches(text, start == 0 ? wpa_cli_cmd_gen : wpa_cli_dummy_gen); } #endif /* CONFIG_READLINE */ static void wpa_cli_interactive(void) { #define max_args 10 char cmdbuf[256], *cmd, *argv[max_args], *pos; int argc; #ifdef CONFIG_READLINE char *home, *hfile = NULL; #endif /* CONFIG_READLINE */ printf("\nInteractive mode\n\n"); #ifdef CONFIG_READLINE rl_attempted_completion_function = wpa_cli_completion; home = getenv("HOME"); if (home) { const char *fname = ".wpa_cli_history"; int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1; hfile = os_malloc(hfile_len); if (hfile) { int res; res = os_snprintf(hfile, hfile_len, "%s/%s", home, fname); if (res >= 0 && res < hfile_len) { hfile[hfile_len - 1] = '\0'; read_history(hfile); stifle_history(100); } } } #endif /* CONFIG_READLINE */ do { #ifdef ANDROID wpa_cli_recv_pending(monitor_conn, 0, 0); #else wpa_cli_recv_pending(ctrl_conn, 0, 0); #endif #ifndef CONFIG_NATIVE_WINDOWS alarm(ping_interval); #endif /* CONFIG_NATIVE_WINDOWS */ #ifdef CONFIG_READLINE cmd = readline("> "); if (cmd && *cmd) { HIST_ENTRY *h; while (next_history()) ; h = previous_history(); if (h == NULL || os_strcmp(cmd, h->line) != 0) add_history(cmd); next_history(); } #else /* CONFIG_READLINE */ printf("> "); cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin); #endif /* CONFIG_READLINE */ #ifndef CONFIG_NATIVE_WINDOWS alarm(0); #endif /* CONFIG_NATIVE_WINDOWS */ if (cmd == NULL) break; #ifdef ANDROID wpa_cli_recv_pending(monitor_conn, 0, 0); #else wpa_cli_recv_pending(ctrl_conn, 0, 0); #endif pos = cmd; while (*pos != '\0') { if (*pos == '\n') { *pos = '\0'; break; } pos++; } argc = 0; pos = cmd; for (;;) { while (*pos == ' ') pos++; if (*pos == '\0') break; argv[argc] = pos; argc++; if (argc == max_args) break; if (*pos == '"') { char *pos2 = os_strrchr(pos, '"'); if (pos2) pos = pos2 + 1; } while (*pos != '\0' && *pos != ' ') pos++; if (*pos == ' ') *pos++ = '\0'; } if (argc) wpa_request(ctrl_conn, argc, argv); if (cmd != cmdbuf) os_free(cmd); } while (!wpa_cli_quit); #ifdef CONFIG_READLINE if (hfile) { /* Save command history, excluding lines that may contain * passwords. */ HIST_ENTRY *h; history_set_pos(0); while ((h = current_history())) { char *p = h->line; while (*p == ' ' || *p == '\t') p++; if (cmd_has_sensitive_data(p)) { h = remove_history(where_history()); if (h) { os_free(h->line); os_free(h->data); os_free(h); } else next_history(); } else next_history(); } write_history(hfile); os_free(hfile); } #endif /* CONFIG_READLINE */ }