static const char * parse_windows_proxy_setting (const char *str, struct auto_proxy_info_entry *e, struct gc_arena *gc) { char buf[128]; const char *ret = NULL; struct buffer in; CLEAR (*e); buf_set_read (&in, (const uint8_t *)str, strlen (str)); if (strchr (str, '=') != NULL) { if (buf_parse (&in, '=', buf, sizeof (buf))) ret = string_alloc (buf, gc); } if (buf_parse (&in, ':', buf, sizeof (buf))) e->server = string_alloc (buf, gc); if (e->server && buf_parse (&in, '\0', buf, sizeof (buf))) e->port = atoi (buf); return ret; }
void ifconfig_pool_read(struct ifconfig_pool_persist *persist, struct ifconfig_pool *pool) { const int buf_size = 128; update_time(); if (persist && persist->file && pool) { struct gc_arena gc = gc_new(); struct buffer in = alloc_buf_gc(256, &gc); char *cn_buf; char *ip_buf; int line = 0; ALLOC_ARRAY_CLEAR_GC(cn_buf, char, buf_size, &gc); ALLOC_ARRAY_CLEAR_GC(ip_buf, char, buf_size, &gc); while (true) { ASSERT(buf_init(&in, 0)); if (!status_read(persist->file, &in)) { break; } ++line; if (BLEN(&in)) { int c = *BSTR(&in); if (c == '#' || c == ';') { continue; } msg( M_INFO, "ifconfig_pool_read(), in='%s', TODO: IPv6", BSTR(&in) ); if (buf_parse(&in, ',', cn_buf, buf_size) && buf_parse(&in, ',', ip_buf, buf_size)) { bool succeeded; const in_addr_t addr = getaddr(GETADDR_HOST_ORDER, ip_buf, 0, &succeeded, NULL); if (succeeded) { msg( M_INFO, "succeeded -> ifconfig_pool_set()"); ifconfig_pool_set(pool, cn_buf, addr, persist->fixed); } } } } ifconfig_pool_msg(pool, D_IFCONFIG_POOL); gc_free(&gc); } }
/* * See management/management-notes.txt for more info on the * the dynamic challenge/response protocol implemented here. */ struct auth_challenge_info * get_auth_challenge (const char *auth_challenge, struct gc_arena *gc) { if (auth_challenge) { struct auth_challenge_info *ac; const int len = strlen (auth_challenge); char *work = (char *) gc_malloc (len+1, false, gc); char *cp; struct buffer b; buf_set_read (&b, (const uint8_t *)auth_challenge, len); ALLOC_OBJ_CLEAR_GC (ac, struct auth_challenge_info, gc); /* parse prefix */ if (!buf_parse(&b, ':', work, len)) return NULL; if (strcmp(work, "CRV1")) return NULL; /* parse flags */ if (!buf_parse(&b, ':', work, len)) return NULL; for (cp = work; *cp != '\0'; ++cp) { const char c = *cp; if (c == 'E') ac->flags |= CR_ECHO; else if (c == 'R') ac->flags |= CR_RESPONSE; } /* parse state ID */ if (!buf_parse(&b, ':', work, len)) return NULL; ac->state_id = string_alloc(work, gc); /* parse user name */ if (!buf_parse(&b, ':', work, len)) return NULL; ac->user = (char *) gc_malloc (strlen(work)+1, true, gc); openvpn_base64_decode(work, (void*)ac->user, -1); /* parse challenge text */ ac->challenge_text = string_alloc(BSTR(&b), gc); return ac; } else return NULL; }
static bool in_src_get (const struct in_src *is, char *line, const int size) { if (is->type == IS_TYPE_FP) { return BOOL_CAST (fgets (line, size, is->u.fp)); } else if (is->type == IS_TYPE_BUF) { bool status = buf_parse (is->u.multiline, '\n', line, size); if ((int) strlen (line) + 1 < size) strcat (line, "\n"); return status; } else { return false; } }
static void push_update_digest(md_ctx_t *ctx, struct buffer *buf, const struct options *opt) { char line[OPTION_PARM_SIZE]; while (buf_parse(buf, ',', line, sizeof(line))) { /* peer-id might change on restart and this should not trigger reopening tun */ if (strprefix(line, "peer-id ")) { continue; } /* tun reopen only needed if cipher change can change tun MTU */ if (strprefix(line, "cipher ") && !opt->ce.tun_mtu_defined) { continue; } md_ctx_update(ctx, (const uint8_t *) line, strlen(line)+1); } }
static void parse_windows_proxy_setting_list (const char *str, const char *type, struct auto_proxy_info_entry *e, struct gc_arena *gc) { struct gc_arena gc_local = gc_new (); struct auto_proxy_info_entry el; CLEAR (*e); if (type) { char buf[128]; struct buffer in; buf_set_read (&in, (const uint8_t *)str, strlen (str)); if (strchr (str, '=') != NULL) { while (buf_parse (&in, ' ', buf, sizeof (buf))) { const char *t = parse_windows_proxy_setting (buf, &el, &gc_local); if (t && !strcmp (t, type)) goto found; } } } else { if (!parse_windows_proxy_setting (str, &el, &gc_local)) goto found; } goto done; found: if (el.server && el.port > 0) { e->server = string_alloc (el.server, gc); e->port = el.port; } done: gc_free (&gc_local); }
bool get_user_pass_cr(struct user_pass *up, const char *auth_file, const char *prefix, const unsigned int flags, const char *auth_challenge) { struct gc_arena gc = gc_new(); if (!up->defined) { bool from_authfile = (auth_file && !streq(auth_file, "stdin")); bool username_from_stdin = false; bool password_from_stdin = false; bool response_from_stdin = true; if (flags & GET_USER_PASS_PREVIOUS_CREDS_FAILED) { msg(M_WARN, "Note: previous '%s' credentials failed", prefix); } #ifdef ENABLE_MANAGEMENT /* * Get username/password from management interface? */ if (management && (!from_authfile && (flags & GET_USER_PASS_MANAGEMENT)) && management_query_user_pass_enabled(management)) { const char *sc = NULL; response_from_stdin = false; if (flags & GET_USER_PASS_PREVIOUS_CREDS_FAILED) { management_auth_failure(management, prefix, "previous auth credentials failed"); } #ifdef ENABLE_CLIENT_CR if (auth_challenge && (flags & GET_USER_PASS_STATIC_CHALLENGE)) { sc = auth_challenge; } #endif if (!management_query_user_pass(management, up, prefix, flags, sc)) { if ((flags & GET_USER_PASS_NOFATAL) != 0) { return false; } else { msg(M_FATAL, "ERROR: could not read %s username/password/ok/string from management interface", prefix); } } } else #endif /* ifdef ENABLE_MANAGEMENT */ /* * Get NEED_OK confirmation from the console */ if (flags & GET_USER_PASS_NEED_OK) { struct buffer user_prompt = alloc_buf_gc(128, &gc); buf_printf(&user_prompt, "NEED-OK|%s|%s:", prefix, up->username); if (!query_user_SINGLE(BSTR(&user_prompt), BLEN(&user_prompt), up->password, USER_PASS_LEN, false)) { msg(M_FATAL, "ERROR: could not read %s ok-confirmation from stdin", prefix); } if (!strlen(up->password)) { strcpy(up->password, "ok"); } } else if (flags & GET_USER_PASS_INLINE_CREDS) { struct buffer buf; buf_set_read(&buf, (uint8_t *) auth_file, strlen(auth_file) + 1); if (!(flags & GET_USER_PASS_PASSWORD_ONLY)) { buf_parse(&buf, '\n', up->username, USER_PASS_LEN); } buf_parse(&buf, '\n', up->password, USER_PASS_LEN); } /* * Read from auth file unless this is a dynamic challenge request. */ else if (from_authfile && !(flags & GET_USER_PASS_DYNAMIC_CHALLENGE)) { /* * Try to get username/password from a file. */ FILE *fp; char password_buf[USER_PASS_LEN] = { '\0' }; fp = platform_fopen(auth_file, "r"); if (!fp) { msg(M_ERR, "Error opening '%s' auth file: %s", prefix, auth_file); } if ((flags & GET_USER_PASS_PASSWORD_ONLY) == 0) { /* Read username first */ if (fgets(up->username, USER_PASS_LEN, fp) == NULL) { msg(M_FATAL, "Error reading username from %s authfile: %s", prefix, auth_file); } } chomp(up->username); if (fgets(password_buf, USER_PASS_LEN, fp) != NULL) { chomp(password_buf); } if (flags & GET_USER_PASS_PASSWORD_ONLY && !password_buf[0]) { msg(M_FATAL, "Error reading password from %s authfile: %s", prefix, auth_file); } if (password_buf[0]) { strncpy(up->password, password_buf, USER_PASS_LEN); } else { password_from_stdin = 1; } fclose(fp); if (!(flags & GET_USER_PASS_PASSWORD_ONLY) && strlen(up->username) == 0) { msg(M_FATAL, "ERROR: username from %s authfile '%s' is empty", prefix, auth_file); } } else { username_from_stdin = true; password_from_stdin = true; } /* * Get username/password from standard input? */ if (username_from_stdin || password_from_stdin || response_from_stdin) { #ifdef ENABLE_CLIENT_CR if (auth_challenge && (flags & GET_USER_PASS_DYNAMIC_CHALLENGE) && response_from_stdin) { struct auth_challenge_info *ac = get_auth_challenge(auth_challenge, &gc); if (ac) { char *response = (char *) gc_malloc(USER_PASS_LEN, false, &gc); struct buffer packed_resp, challenge; challenge = alloc_buf_gc(14+strlen(ac->challenge_text), &gc); buf_printf(&challenge, "CHALLENGE: %s", ac->challenge_text); buf_set_write(&packed_resp, (uint8_t *)up->password, USER_PASS_LEN); if (!query_user_SINGLE(BSTR(&challenge), BLEN(&challenge), response, USER_PASS_LEN, BOOL_CAST(ac->flags&CR_ECHO))) { msg(M_FATAL, "ERROR: could not read challenge response from stdin"); } strncpynt(up->username, ac->user, USER_PASS_LEN); buf_printf(&packed_resp, "CRV1::%s::%s", ac->state_id, response); } else { msg(M_FATAL, "ERROR: received malformed challenge request from server"); } } else #endif /* ifdef ENABLE_CLIENT_CR */ { struct buffer user_prompt = alloc_buf_gc(128, &gc); struct buffer pass_prompt = alloc_buf_gc(128, &gc); query_user_clear(); buf_printf(&user_prompt, "Enter %s Username:"******"Enter %s Password:"******"ERROR: Failed retrieving username or password"); } if (!(flags & GET_USER_PASS_PASSWORD_ONLY)) { if (strlen(up->username) == 0) { msg(M_FATAL, "ERROR: %s username is empty", prefix); } } #ifdef ENABLE_CLIENT_CR if (auth_challenge && (flags & GET_USER_PASS_STATIC_CHALLENGE) && response_from_stdin) { char *response = (char *) gc_malloc(USER_PASS_LEN, false, &gc); struct buffer packed_resp, challenge; char *pw64 = NULL, *resp64 = NULL; challenge = alloc_buf_gc(14+strlen(auth_challenge), &gc); buf_printf(&challenge, "CHALLENGE: %s", auth_challenge); if (!query_user_SINGLE(BSTR(&challenge), BLEN(&challenge), response, USER_PASS_LEN, BOOL_CAST(flags & GET_USER_PASS_STATIC_CHALLENGE_ECHO))) { msg(M_FATAL, "ERROR: could not retrieve static challenge response"); } if (openvpn_base64_encode(up->password, strlen(up->password), &pw64) == -1 || openvpn_base64_encode(response, strlen(response), &resp64) == -1) { msg(M_FATAL, "ERROR: could not base64-encode password/static_response"); } buf_set_write(&packed_resp, (uint8_t *)up->password, USER_PASS_LEN); buf_printf(&packed_resp, "SCRV1:%s:%s", pw64, resp64); string_clear(pw64); free(pw64); string_clear(resp64); free(resp64); } #endif /* ifdef ENABLE_CLIENT_CR */ } } string_mod(up->username, CC_PRINT, CC_CRLF, 0); string_mod(up->password, CC_PRINT, CC_CRLF, 0); up->defined = true; } #if 0 msg(M_INFO, "GET_USER_PASS %s u='%s' p='%s'", prefix, up->username, up->password); #endif gc_free(&gc); return true; }