void scriptapi_create_auth(lua_State *L, const std::string &playername, const std::string &password) { realitycheck(L); assert(lua_checkstack(L, 20)); StackUnroller stack_unroller(L); get_auth_handler(L); lua_getfield(L, -1, "create_auth"); if(lua_type(L, -1) != LUA_TFUNCTION) throw LuaError(L, "Authentication handler missing create_auth"); lua_pushstring(L, playername.c_str()); lua_pushstring(L, password.c_str()); if(lua_pcall(L, 2, 0, 0)) script_error(L, "error: %s", lua_tostring(L, -1)); }
bool scriptapi_get_auth(lua_State *L, const std::string &playername, std::string *dst_password, std::set<std::string> *dst_privs) { realitycheck(L); assert(lua_checkstack(L, 20)); StackUnroller stack_unroller(L); get_auth_handler(L); lua_getfield(L, -1, "get_auth"); if(lua_type(L, -1) != LUA_TFUNCTION) throw LuaError(L, "Authentication handler missing get_auth"); lua_pushstring(L, playername.c_str()); if(lua_pcall(L, 1, 1, 0)) script_error(L, "error: %s", lua_tostring(L, -1)); // nil = login not allowed if(lua_isnil(L, -1)) return false; luaL_checktype(L, -1, LUA_TTABLE); std::string password; bool found = getstringfield(L, -1, "password", password); if(!found) throw LuaError(L, "Authentication handler didn't return password"); if(dst_password) *dst_password = password; lua_getfield(L, -1, "privileges"); if(!lua_istable(L, -1)) throw LuaError(L, "Authentication handler didn't return privilege table"); if(dst_privs) read_privileges(L, -1, *dst_privs); lua_pop(L, 1); return true; }
int post_auth_handler(worker_st * ws, unsigned http_ver) { int ret = -1, sd = -1; struct http_req_st *req = &ws->req; const char *reason = "Authentication failed"; char *username = NULL; char *password = NULL; char *groupname = NULL; char *msg = NULL; unsigned def_group = 0; if (req->body_length > 0) { oclog(ws, LOG_HTTP_DEBUG, "POST body: '%.*s'", (int)req->body_length, req->body); } if (ws->sid_set && ws->auth_state == S_AUTH_INACTIVE) ws->auth_state = S_AUTH_INIT; if (ws->auth_state == S_AUTH_INACTIVE) { SecAuthInitMsg ireq = SEC_AUTH_INIT_MSG__INIT; ret = parse_reply(ws, req->body, req->body_length, GROUPNAME_FIELD, sizeof(GROUPNAME_FIELD)-1, GROUPNAME_FIELD_XML, sizeof(GROUPNAME_FIELD_XML)-1, &groupname); if (ret < 0) { ret = parse_reply(ws, req->body, req->body_length, GROUPNAME_FIELD2, sizeof(GROUPNAME_FIELD2)-1, GROUPNAME_FIELD_XML, sizeof(GROUPNAME_FIELD_XML)-1, &groupname); } if (ret < 0) { oclog(ws, LOG_HTTP_DEBUG, "failed reading groupname"); } else { if (ws->config->default_select_group != NULL && strcmp(groupname, ws->config->default_select_group) == 0) { def_group = 1; } else { strlcpy(ws->groupname, groupname, sizeof(ws->groupname)); ireq.group_name = ws->groupname; } } talloc_free(groupname); if (ws->selected_auth->type & AUTH_TYPE_GSSAPI) { if (req->authorization == NULL || req->authorization_size == 0) return basic_auth_handler(ws, http_ver, NULL); if (req->authorization_size > 10) { ireq.user_name = req->authorization + 10; ireq.auth_type |= AUTH_TYPE_GSSAPI; } else { oclog(ws, LOG_HTTP_DEBUG, "Invalid authorization data: %.*s", req->authorization_size, req->authorization); goto auth_fail; } } if (ws->selected_auth->type & AUTH_TYPE_USERNAME_PASS) { ret = parse_reply(ws, req->body, req->body_length, USERNAME_FIELD, sizeof(USERNAME_FIELD)-1, NULL, 0, &username); if (ret < 0) { oclog(ws, LOG_HTTP_DEBUG, "failed reading username"); goto ask_auth; } strlcpy(ws->username, username, sizeof(ws->username)); talloc_free(username); ireq.user_name = ws->username; ireq.auth_type |= AUTH_TYPE_USERNAME_PASS; } if (ws->selected_auth->type & AUTH_TYPE_CERTIFICATE) { if (ws->cert_auth_ok == 0) { reason = MSG_NO_CERT_ERROR; oclog(ws, LOG_INFO, "no certificate provided for authentication"); goto auth_fail; } else { ret = get_cert_info(ws); if (ret < 0) { reason = MSG_CERT_READ_ERROR; oclog(ws, LOG_ERR, "failed reading certificate info"); goto auth_fail; } } if (def_group == 0 && ws->cert_groups_size > 0 && ws->groupname[0] == 0) { oclog(ws, LOG_HTTP_DEBUG, "user has not selected a group"); return get_auth_handler2(ws, http_ver, "Please select your group"); } ireq.tls_auth_ok = ws->cert_auth_ok; ireq.cert_user_name = ws->cert_username; ireq.cert_group_names = ws->cert_groups; ireq.n_cert_group_names = ws->cert_groups_size; ireq.auth_type |= AUTH_TYPE_CERTIFICATE; } ireq.hostname = req->hostname; ireq.ip = ws->remote_ip_str; sd = connect_to_secmod(ws); if (sd == -1) { reason = MSG_INTERNAL_ERROR; oclog(ws, LOG_ERR, "failed connecting to sec mod"); goto auth_fail; } ret = send_msg_to_secmod(ws, sd, SM_CMD_AUTH_INIT, &ireq, (pack_size_func) sec_auth_init_msg__get_packed_size, (pack_func) sec_auth_init_msg__pack); if (ret < 0) { reason = MSG_INTERNAL_ERROR; oclog(ws, LOG_ERR, "failed sending auth init message to sec mod"); goto auth_fail; } ws->auth_state = S_AUTH_INIT; } else if (ws->auth_state == S_AUTH_INIT || ws->auth_state == S_AUTH_REQ) { SecAuthContMsg areq = SEC_AUTH_CONT_MSG__INIT; areq.ip = ws->remote_ip_str; if (ws->selected_auth->type & AUTH_TYPE_GSSAPI) { if (req->authorization == NULL || req->authorization_size <= 10) { if (req->authorization != NULL) oclog(ws, LOG_HTTP_DEBUG, "Invalid authorization data: %.*s", req->authorization_size, req->authorization); goto auth_fail; } areq.password = req->authorization + 10; } if (areq.password == NULL && ws->selected_auth->type & AUTH_TYPE_USERNAME_PASS) { ret = parse_reply(ws, req->body, req->body_length, PASSWORD_FIELD, sizeof(PASSWORD_FIELD)-1, NULL, 0, &password); if (ret < 0) { reason = MSG_NO_PASSWORD_ERROR; oclog(ws, LOG_ERR, "failed reading password"); goto auth_fail; } areq.password = password; } if (areq.password != NULL) { if (ws->sid_set != 0) { areq.sid.data = ws->sid; areq.sid.len = sizeof(ws->sid); } sd = connect_to_secmod(ws); if (sd == -1) { reason = MSG_INTERNAL_ERROR; oclog(ws, LOG_ERR, "failed connecting to sec mod"); goto auth_fail; } ret = send_msg_to_secmod(ws, sd, SM_CMD_AUTH_CONT, &areq, (pack_size_func) sec_auth_cont_msg__get_packed_size, (pack_func) sec_auth_cont_msg__pack); talloc_free(password); if (ret < 0) { reason = MSG_INTERNAL_ERROR; oclog(ws, LOG_ERR, "failed sending auth req message to main"); goto auth_fail; } ws->auth_state = S_AUTH_REQ; } else goto auth_fail; } else { oclog(ws, LOG_ERR, "unexpected POST request in auth state %u", (unsigned)ws->auth_state); goto auth_fail; } ret = recv_auth_reply(ws, sd, &msg); if (sd != -1) { close(sd); sd = -1; } if (ret == ERR_AUTH_CONTINUE) { oclog(ws, LOG_DEBUG, "continuing authentication for '%s'", ws->username); ws->auth_state = S_AUTH_REQ; if (ws->selected_auth->type & AUTH_TYPE_GSSAPI) { ret = basic_auth_handler(ws, http_ver, msg); } else { ret = get_auth_handler2(ws, http_ver, msg); } goto cleanup; } else if (ret < 0) { if (ws->selected_auth->type & AUTH_TYPE_GSSAPI) { /* Fallback from GSSAPI to USERNAME-PASSWORD */ ws_disable_auth(ws, AUTH_TYPE_GSSAPI); oclog(ws, LOG_ERR, "failed gssapi authentication"); if (ws_switch_auth_to(ws, AUTH_TYPE_USERNAME_PASS) == 0) goto auth_fail; ws->auth_state = S_AUTH_INACTIVE; ws->sid_set = 0; goto ask_auth; } else { oclog(ws, LOG_ERR, "failed authentication for '%s'", ws->username); goto auth_fail; } } oclog(ws, LOG_HTTP_DEBUG, "user '%s' obtained cookie", ws->username); ws->auth_state = S_AUTH_COOKIE; ret = post_common_handler(ws, http_ver, msg); goto cleanup; ask_auth: return get_auth_handler(ws, http_ver); auth_fail: if (sd != -1) close(sd); oclog(ws, LOG_HTTP_DEBUG, "HTTP sending: 401 Unauthorized"); cstp_printf(ws, "HTTP/1.%d 401 Unauthorized\r\nContent-Length: 0\r\nX-Reason: %s\r\n\r\n", http_ver, reason); cstp_fatal_close(ws, GNUTLS_A_ACCESS_DENIED); talloc_free(msg); exit_worker(ws); cleanup: talloc_free(msg); return ret; }