static int uwsgi_routing_func_basicauth(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) { // skip if already authenticated if (wsgi_req->remote_user_len > 0) { return UWSGI_ROUTE_NEXT; } if (wsgi_req->authorization_len > 7 && ur->data2_len > 0) { if (strncmp(wsgi_req->authorization, "Basic ", 6)) goto forbidden; size_t auth_len = 0; char *auth = uwsgi_base64_decode(wsgi_req->authorization+6, wsgi_req->authorization_len-6, &auth_len); if (auth) { if (!ur->custom) { // check htpasswd-like file uint16_t ulen = htpasswd_check(ur->data2, auth); if (ulen > 0) { wsgi_req->remote_user = uwsgi_req_append(wsgi_req, "REMOTE_USER", 11, auth, ulen); if (!wsgi_req->remote_user) { free(auth); goto forbidden; } wsgi_req->remote_user_len = ulen; } else if (ur->data3_len == 0) { free(auth); goto forbidden; } } else { if (!uwsgi_strncmp(auth, auth_len, ur->data2, ur->data2_len)) { wsgi_req->remote_user = uwsgi_req_append(wsgi_req, "REMOTE_USER", 11, auth, ur->custom); if (!wsgi_req->remote_user) { free(auth); goto forbidden; } wsgi_req->remote_user_len = ur->custom; } else if (ur->data3_len == 0) { free(auth); goto forbidden; } } free(auth); return UWSGI_ROUTE_NEXT; } } forbidden: if (uwsgi_response_prepare_headers(wsgi_req, "401 Authorization Required", 26)) goto end; char *realm = uwsgi_concat3n("Basic realm=\"", 13, ur->data, ur->data_len, "\"", 1); // no need to check for errors uwsgi_response_add_header(wsgi_req, "WWW-Authenticate", 16, realm, 13 + ur->data_len + 1); free(realm); uwsgi_response_write_body_do(wsgi_req, "Unauthorized", 12); end: return UWSGI_ROUTE_BREAK; }
static int uwsgi_routing_func_rewrite(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) { char *tmp_qs = NULL; char **subject = (char **) (((char *)(wsgi_req))+ur->subject); uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len); struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len); if (!ub) return UWSGI_ROUTE_BREAK; uint16_t path_info_len = ub->pos; uint16_t query_string_len = 0; char *query_string = memchr(ub->buf, '?', ub->pos); if (query_string) { path_info_len = query_string - ub->buf; query_string++; query_string_len = ub->pos - (path_info_len + 1); if (wsgi_req->query_string_len > 0) { tmp_qs = uwsgi_concat4n(query_string, query_string_len, "&", 1, wsgi_req->query_string, wsgi_req->query_string_len, "", 0); query_string = tmp_qs; query_string_len = strlen(query_string); } } // over engineering, could be required in the future... else { if (wsgi_req->query_string_len > 0) { query_string = wsgi_req->query_string; query_string_len = wsgi_req->query_string_len; } else { query_string = ""; } } char *ptr = uwsgi_req_append(wsgi_req, "PATH_INFO", 9, ub->buf, path_info_len); if (!ptr) goto clear; // set new path_info wsgi_req->path_info = ptr; wsgi_req->path_info_len = path_info_len; ptr = uwsgi_req_append(wsgi_req, "QUERY_STRING", 12, query_string, query_string_len); if (!ptr) goto clear; // set new query_string wsgi_req->query_string = ptr; wsgi_req->query_string_len = query_string_len; uwsgi_buffer_destroy(ub); if (tmp_qs) free(tmp_qs); if (ur->custom) return UWSGI_ROUTE_CONTINUE; return UWSGI_ROUTE_NEXT; clear: uwsgi_buffer_destroy(ub); if (tmp_qs) free(tmp_qs); return UWSGI_ROUTE_BREAK; }
int uwsgi_routing_func_rewrite(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) { char *tmp_qs = NULL; char **subject = (char **) (((char *)(wsgi_req))+ur->subject); uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len); char *path_info = uwsgi_regexp_apply_ovec(*subject, *subject_len, ur->data, ur->data_len, ur->ovector, ur->ovn); uint16_t path_info_len = strlen(path_info); uint16_t query_string_len = 0; char *query_string = strchr(path_info, '?'); if (query_string) { path_info_len = query_string - path_info; query_string++; query_string_len = strlen(query_string); if (wsgi_req->query_string_len > 0) { tmp_qs = uwsgi_concat4n(query_string, query_string_len, "&", 1, wsgi_req->query_string, wsgi_req->query_string_len, "", 0); query_string = tmp_qs; query_string_len = strlen(query_string); } } // over engineering, could be required in the future... else { if (wsgi_req->query_string_len > 0) { query_string = wsgi_req->query_string; query_string_len = wsgi_req->query_string_len; } else { query_string = ""; } } char *ptr = uwsgi_req_append(wsgi_req, "PATH_INFO", 9, path_info, path_info_len); if (!ptr) goto clear; // set new path_info wsgi_req->path_info = ptr; wsgi_req->path_info_len = path_info_len; ptr = uwsgi_req_append(wsgi_req, "QUERY_STRING", 12, query_string, query_string_len); if (!ptr) goto clear; // set new query_string wsgi_req->query_string = ptr; wsgi_req->query_string_len = query_string_len; free(path_info); if (tmp_qs) free(tmp_qs); if (ur->custom) return UWSGI_ROUTE_CONTINUE; return UWSGI_ROUTE_NEXT; clear: free(path_info); if (tmp_qs) free(tmp_qs); return UWSGI_ROUTE_BREAK; }
int uwsgi_routing_func_uwsgi_simple(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) { struct uwsgi_header *uh = (struct uwsgi_header *) ur->data; wsgi_req->uh.modifier1 = uh->modifier1; wsgi_req->uh.modifier2 = uh->modifier2; // set appid if (ur->data2_len > 0) { wsgi_req->appid = ur->data2; wsgi_req->appid_len = ur->data2_len; char *ptr = uwsgi_req_append(wsgi_req, "UWSGI_APPID", 11, ur->data2, ur->data2_len); if (ptr) { // fill iovec if (wsgi_req->var_cnt + 2 < uwsgi.vec_size - (4 + 1)) { wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptr - (2 + 11); wsgi_req->hvec[wsgi_req->var_cnt].iov_len = 11; wsgi_req->var_cnt++; wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptr; wsgi_req->hvec[wsgi_req->var_cnt].iov_len = ur->data2_len; wsgi_req->var_cnt++; } } } return UWSGI_ROUTE_CONTINUE; }
int uwsgi_routing_func_uwsgi_remote(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) { struct uwsgi_header *uh = (struct uwsgi_header *) ur->data; char *addr = ur->data + sizeof(struct uwsgi_header); // mark a route request wsgi_req->status = -17; // append appid if (ur->data2_len > 0) { uwsgi_req_append(wsgi_req, "UWSGI_APPID", 11, ur->data2, ur->data2_len); } // ok now if have offload threads, directly use them if (wsgi_req->socket->can_offload) { struct uwsgi_buffer *ub = uwsgi_buffer_new(4 + wsgi_req->uh.pktsize); if (ub) { uh->pktsize = wsgi_req->uh.pktsize; if (uwsgi_buffer_append(ub, (char *) uh, 4)) goto bad; if (uwsgi_buffer_append(ub, wsgi_req->buffer, uh->pktsize)) goto bad; if (!uwsgi_offload_request_net_do(wsgi_req, addr, ub)) { wsgi_req->status = -30; return UWSGI_ROUTE_BREAK; } bad: uwsgi_buffer_destroy(ub); } } int uwsgi_fd = uwsgi_connect(addr, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0); if (uwsgi_fd < 0) { uwsgi_log("unable to connect to host %s\n", addr); return UWSGI_ROUTE_NEXT; } int post_fd = wsgi_req->poll.fd; if (wsgi_req->async_post) { post_fd = fileno((FILE*)wsgi_req->async_post); } if (uwsgi_send_message(uwsgi_fd, uh->modifier1, uh->modifier2, wsgi_req->buffer, wsgi_req->uh.pktsize, post_fd, wsgi_req->post_cl, 0) < 0) { uwsgi_log("unable to send uwsgi request to host %s", addr); return UWSGI_ROUTE_NEXT; } ssize_t ret = uwsgi_pipe(uwsgi_fd, wsgi_req->poll.fd, 0); if (ret > 0) { wsgi_req->response_size += ret; } else { uwsgi_log("unable to manage uwsgi route response for %s\n", addr); } close(uwsgi_fd); return UWSGI_ROUTE_BREAK; }
static int uwsgi_routing_func_hash(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) { struct uwsgi_router_hash_conf *urhc = (struct uwsgi_router_hash_conf *) ur->data2; struct uwsgi_hash_algo *uha = uwsgi_hash_algo_get(urhc->algo); if (!uha) { uwsgi_log("[uwsgi-hash-router] unable to find hash algo \"%s\"\n", urhc->algo); return UWSGI_ROUTE_BREAK; } char **subject = (char **) (((char *)(wsgi_req))+ur->subject); uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len); struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urhc->key, urhc->key_len); if (!ub) return UWSGI_ROUTE_BREAK; uint32_t h = uha->func(ub->buf, ub->pos); uwsgi_buffer_destroy(ub); // now count the number of items uint32_t items = 1; size_t i, ilen = urhc->items_len; for(i=0; i<ilen; i++) { if (urhc->items[i] == ';') items++; } // skip last semicolon if (urhc->items[ilen-1] == ';') items--; uint32_t hashed_result = h % items; uint32_t found = 0; char *value = urhc->items; uint16_t vallen = 0; for(i=0; i<ilen; i++) { if (!value) { value = urhc->items + i; } if (urhc->items[i] == ';') { if (found == hashed_result) { vallen = (urhc->items+i) - value; break; } value = NULL; found++; } } if (vallen == 0) { // first item if (hashed_result == 0) { value = urhc->items; vallen = urhc->items_len; } // last item else { vallen = (urhc->items + urhc->items_len) - value; } } if (!vallen) { uwsgi_log("[uwsgi-hash-router] BUG !!! unable to hash items\n"); return UWSGI_ROUTE_BREAK; } if (!uwsgi_req_append(wsgi_req, urhc->var, urhc->var_len, value, vallen)) { uwsgi_log("[uwsgi-hash-router] unable to append hash var to the request\n"); return UWSGI_ROUTE_BREAK; } return UWSGI_ROUTE_NEXT; }