/// This differs from the non-unique version in that we expect the filename /// to be something like a pattern for mkstemp(), so the resulting path can /// reside in a system-wide directory with no risk of a conflict. static char * resolve_relative_runtime_unique_filename (const char *filename) { struct str path; str_init (&path); const char *runtime_dir = getenv ("XDG_RUNTIME_DIR"); if (runtime_dir && *runtime_dir == '/') str_append (&path, runtime_dir); else str_append (&path, "/tmp"); str_append_printf (&path, "/%s/%s", PROGRAM_NAME, filename); // Try to create the file's ancestors; // typically the user will want to immediately create a file in there const char *last_slash = strrchr (path.str, '/'); if (last_slash && last_slash != path.str) { char *copy = xstrndup (path.str, last_slash - path.str); (void) mkdir_with_parents (copy, NULL); free (copy); } return str_steal (&path); }
int get_auth_handler2(worker_st * ws, unsigned http_ver, const char *pmsg) { int ret; char context[BASE64_LENGTH(SID_SIZE) + 1]; unsigned int i, j; str_st str; const char *login_msg_start; const char *login_msg_end; if (ws->req.user_agent_type == AGENT_OPENCONNECT_V3) { login_msg_start = OCV3_LOGIN_MSG_START; login_msg_end = ocv3_login_msg_end; } else { login_msg_start = OC_LOGIN_MSG_START; login_msg_end = oc_login_msg_end; } if (ws->selected_auth->type & AUTH_TYPE_GSSAPI && ws->auth_state < S_AUTH_COOKIE) { if (ws->req.authorization == NULL || ws->req.authorization_size == 0) return basic_auth_handler(ws, http_ver, NULL); else return post_auth_handler(ws, http_ver); } str_init(&str, ws); oclog(ws, LOG_HTTP_DEBUG, "HTTP sending: 200 OK"); cstp_cork(ws); ret = cstp_printf(ws, "HTTP/1.%u 200 OK\r\n", http_ver); if (ret < 0) return -1; if (ws->sid_set != 0) { base64_encode((char *)ws->sid, sizeof(ws->sid), (char *)context, sizeof(context)); ret = cstp_printf(ws, "Set-Cookie: webvpncontext=%s; Max-Age=%u; Secure\r\n", context, (unsigned)ws->config->cookie_timeout); if (ret < 0) return -1; oclog(ws, LOG_DEBUG, "sent sid: %s", context); } else { ret = cstp_puts(ws, "Set-Cookie: webvpncontext=; expires=Thu, 01 Jan 1970 22:00:00 GMT; path=/; Secure\r\n"); if (ret < 0) return -1; } ret = cstp_puts(ws, "Content-Type: text/xml\r\n"); if (ret < 0) { ret = -1; goto cleanup; } if (ws->auth_state == S_AUTH_REQ) { /* only ask password */ if (pmsg == NULL) pmsg = "Please enter your password"; ret = str_append_printf(&str, login_msg_start, pmsg); if (ret < 0) { ret = -1; goto cleanup; } ret = str_append_str(&str, login_msg_password); if (ret < 0) { ret = -1; goto cleanup; } ret = str_append_str(&str, login_msg_end); if (ret < 0) { ret = -1; goto cleanup; } } else { if (pmsg == NULL) pmsg = "Please enter your username"; /* ask for username and groups */ ret = str_append_printf(&str, login_msg_start, pmsg); if (ret < 0) { ret = -1; goto cleanup; } if (ws->selected_auth->type & AUTH_TYPE_USERNAME_PASS) { ret = str_append_str(&str, login_msg_user); if (ret < 0) { ret = -1; goto cleanup; } } if (ws->selected_auth->type & AUTH_TYPE_CERTIFICATE && ws->cert_auth_ok != 0) { ret = get_cert_info(ws); if (ret < 0) { ret = -1; oclog(ws, LOG_WARNING, "cannot obtain certificate information"); goto cleanup; } } /* send groups */ if (ws->config->group_list_size > 0 || ws->cert_groups_size > 0) { ret = str_append_str(&str, "<select name=\"group_list\" label=\"GROUP:\">\n"); if (ret < 0) { ret = -1; goto cleanup; } /* Several anyconnect clients (and openconnect) submit the group name * separately in that form. In that case they expect that we re-order * the list and we place the group they selected first. WTF! No respect * to server time. */ if (ws->groupname[0] != 0) { ret = append_group_str(ws, &str, ws->groupname); if (ret < 0) { ret = -1; goto cleanup; } } if (ws->config->default_select_group) { ret = str_append_printf(&str, "<option>%s</option>\n", ws->config->default_select_group); if (ret < 0) { ret = -1; goto cleanup; } } /* append any groups available in the certificate */ if (ws->selected_auth->type & AUTH_TYPE_CERTIFICATE && ws->cert_auth_ok != 0) { unsigned dup; for (i=0;i<ws->cert_groups_size;i++) { dup = 0; for (j=0;j<ws->config->group_list_size;j++) { if (strcmp(ws->cert_groups[i], ws->config->group_list[j]) == 0) { dup = 1; break; } } if (dup == 0 && ws->groupname[0] != 0 && strcmp(ws->groupname, ws->cert_groups[i]) == 0) dup = 1; if (dup != 0) continue; ret = str_append_printf(&str, "<option>%s</option>\n", ws->cert_groups[i]); if (ret < 0) { ret = -1; goto cleanup; } } } for (i=0;i<ws->config->group_list_size;i++) { if (ws->groupname[0] != 0 && strcmp(ws->groupname, ws->config->group_list[i]) == 0) continue; ret = append_group_idx(ws, &str, i); if (ret < 0) { ret = -1; goto cleanup; } } ret = str_append_str(&str, "</select>\n"); if (ret < 0) { ret = -1; goto cleanup; } } ret = str_append_str(&str, login_msg_end); if (ret < 0) { ret = -1; goto cleanup; } } ret = cstp_printf(ws, "Content-Length: %u\r\n", (unsigned int)str.length); if (ret < 0) { ret = -1; goto cleanup; } ret = cstp_puts(ws, "X-Transcend-Version: 1\r\n"); if (ret < 0) { ret = -1; goto cleanup; } ret = cstp_puts(ws, "\r\n"); if (ret < 0) { ret = -1; goto cleanup; } ret = cstp_send(ws, str.data, str.length); if (ret < 0) { ret = -1; goto cleanup; } ret = cstp_uncork(ws); if (ret < 0) { ret = -1; goto cleanup; } ret = 0; cleanup: str_clear(&str); return ret; }