static void cache_simple_command(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) { struct wsgi_request *wsgi_req = (struct wsgi_request *) data; if (vallen > 0) { if (!uwsgi_strncmp(key, keylen, "key", 3)) { uint64_t vallen = 0; char *value = uwsgi_cache_magic_get(val, vallen, &vallen, NULL, NULL); if (value) { uwsgi_response_write_body_do(wsgi_req, value, vallen); free(value); } } else if (!uwsgi_strncmp(key, keylen, "get", 3)) { uint64_t vallen = 0; char *value = uwsgi_cache_magic_get(val, vallen, &vallen, NULL, NULL); if (value) { uwsgi_response_write_body_do(wsgi_req, value, vallen); free(value); } else { uwsgi_404(wsgi_req); } } } }
void fr_get_hostname(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) { struct corerouter_peer *peer = (struct corerouter_peer *) data; struct fastrouter_session *fr = (struct fastrouter_session *) peer->session; //uwsgi_log("%.*s = %.*s\n", keylen, key, vallen, val); if (!uwsgi_strncmp("SERVER_NAME", 11, key, keylen) && !peer->key_len) { peer->key = val; peer->key_len = vallen; return; } if (!uwsgi_strncmp("HTTP_HOST", 9, key, keylen) && !fr->has_key) { peer->key = val; peer->key_len = vallen; return; } if (!uwsgi_strncmp("UWSGI_FASTROUTER_KEY", 20, key, keylen)) { fr->has_key = 1; peer->key = val; peer->key_len = vallen; return; } }
void cache_command(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) { struct wsgi_request *wsgi_req = (struct wsgi_request *) data; uint64_t tmp_vallen = 0; if (vallen > 0) { if (!uwsgi_strncmp(key, keylen, "key", 3)) { val = uwsgi_cache_get(val, vallen, &tmp_vallen); if (val && tmp_vallen > 0) { #ifdef UWSGI_DEBUG uwsgi_log("cache value size: %llu\n", tmp_vallen); #endif wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, val, tmp_vallen); } } else if (!uwsgi_strncmp(key, keylen, "get", 3)) { val = uwsgi_cache_get(val, vallen, &tmp_vallen); if (val && vallen > 0) { wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, val, tmp_vallen); } else { wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 404 Not Found\r\n\r\n<h1>Not Found</h1>", 44); } } } }
int uwsgi_add_expires_type(struct wsgi_request *wsgi_req, char *mime_type, int mime_type_len, struct stat *st) { struct uwsgi_dyn_dict *udd = uwsgi.static_expires_type; time_t now = wsgi_req->start_of_request / 1000000; // 30+1 char expires[31]; while (udd) { if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) { int delta = uwsgi_str_num(udd->value, udd->vallen); int size = set_http_date(now + delta, expires); if (size > 0) { if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1; } return 0; } udd = udd->next; } udd = uwsgi.static_expires_type_mtime; while (udd) { if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) { int delta = uwsgi_str_num(udd->value, udd->vallen); int size = set_http_date(st->st_mtime + delta, expires); if (size > 0) { if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1; } return 0; } udd = udd->next; } return 0; }
void corerouter_manage_subscription(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) { struct uwsgi_subscribe_req *usr = (struct uwsgi_subscribe_req *) data; if (!uwsgi_strncmp("key", 3, key, keylen)) { usr->key = val; usr->keylen = vallen; } else if (!uwsgi_strncmp("address", 7, key, keylen)) { usr->address = val; usr->address_len = vallen; } else if (!uwsgi_strncmp("modifier1", 9, key, keylen)) { usr->modifier1 = uwsgi_str_num(val, vallen); } else if (!uwsgi_strncmp("cores", 5, key, keylen)) { usr->cores = uwsgi_str_num(val, vallen); } else if (!uwsgi_strncmp("load", 4, key, keylen)) { usr->load = uwsgi_str_num(val, vallen); } else if (!uwsgi_strncmp("weight", 6, key, keylen)) { usr->weight = uwsgi_str_num(val, vallen); } else if (!uwsgi_strncmp("unix", 4, key, keylen)) { usr->unix_check = uwsgi_str_num(val, vallen); } else if (!uwsgi_strncmp("sign", 4, key, keylen)) { usr->sign = val; usr->sign_len = vallen; } }
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; }
void fastrouter_manage_subscription(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) { struct uwsgi_subscribe_req *usr = (struct uwsgi_subscribe_req *) data; if (!uwsgi_strncmp("key", 3, key, keylen)) { usr->key = val; usr->keylen = vallen; } else if (!uwsgi_strncmp("address", 7, key, keylen)) { usr->address = val; usr->address_len = vallen; } else if (!uwsgi_strncmp("modifier1", 9, key, keylen)) { usr->modifier1 = uwsgi_str_num(val, vallen); } }
static void fr_get_hostname(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) { struct corerouter_peer *peer = (struct corerouter_peer *) data; struct fastrouter_session *fr = (struct fastrouter_session *) peer->session; //uwsgi_log("%.*s = %.*s\n", keylen, key, vallen, val); if (!uwsgi_strncmp("SERVER_NAME", 11, key, keylen) && !peer->key_len) { if (vallen <= 0xff) { memcpy(peer->key, val, vallen); peer->key_len = vallen; } return; } if (!uwsgi_strncmp("HTTP_HOST", 9, key, keylen) && !fr->has_key) { if (vallen <= 0xff) { memcpy(peer->key, val, vallen); peer->key_len = vallen; } return; } if (!uwsgi_strncmp("UWSGI_FASTROUTER_KEY", 20, key, keylen)) { if (vallen <= 0xff) { fr->has_key = 1; memcpy(peer->key, val, vallen); peer->key_len = vallen; } return; } if (!uwsgi_strncmp("REMOTE_ADDR", 11, key, keylen)) { if (vallen < sizeof(peer->session->client_address)) { strncpy(peer->session->client_address, val, vallen); } return; } if (!uwsgi_strncmp("REMOTE_PORT", 11, key, keylen)) { if (vallen < sizeof(peer->session->client_port)) { strncpy(peer->session->client_port, val, vallen); } return; } }
struct uwsgi_subscribe_slot *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen) { if (keylen > 0xff) return NULL; uint32_t hash = djb33x_hash(key, keylen); int hash_key = hash % 0xffff; struct uwsgi_subscribe_slot *current_slot = slot[hash_key]; #ifdef UWSGI_DEBUG uwsgi_log("****************************\n"); while (current_slot) { uwsgi_log("slot %.*s %d\n", current_slot->keylen, current_slot->key, current_slot->hits); current_slot = current_slot->next; } uwsgi_log("****************************\n"); current_slot = slot[hash_key]; #endif while (current_slot) { if (!uwsgi_strncmp(key, keylen, current_slot->key, current_slot->keylen)) { // auto optimization if (current_slot->prev) { if (current_slot->hits > current_slot->prev->hits) { struct uwsgi_subscribe_slot *slot_parent = current_slot->prev->prev, *slot_prev = current_slot->prev; if (slot_parent) { slot_parent->next = current_slot; } else { slot[hash_key] = current_slot; } if (current_slot->next) { current_slot->next->prev = slot_prev; } slot_prev->prev = current_slot; slot_prev->next = current_slot->next; current_slot->next = slot_prev; current_slot->prev = slot_parent; } } return current_slot; } current_slot = current_slot->next; // check for loopy optimization if (current_slot == slot[hash_key]) break; } return NULL; }
static struct uwsgi_ssi_cmd* uwsgi_ssi_get_cmd(char *name, size_t name_len) { struct uwsgi_ssi_cmd *usc = uwsgi_ssi_commands; while(usc) { if (!uwsgi_strncmp(usc->name, usc->name_len, name, name_len)) { return usc; } usc = usc->next; } return NULL; }
// check if a log should raise an alarm void uwsgi_alarm_log_check(char *msg, size_t len) { if (!uwsgi_strncmp(msg, len, "[uwsgi-alarm", 12)) return; struct uwsgi_alarm_log *ual = uwsgi.alarm_logs; while(ual) { if (uwsgi_regexp_match(ual->pattern, ual->pattern_extra, msg, len) >= 0) { uwsgi_alarm_log_run(ual, msg, len); } ual = ual->next; } }
struct uwsgi_logvar *uwsgi_logvar_get(struct wsgi_request *wsgi_req, char *key, uint8_t keylen) { struct uwsgi_logvar *lv = wsgi_req->logvars; while(lv) { if (!uwsgi_strncmp(key, keylen, lv->key, lv->keylen)) { return lv; } lv = lv->next; } return NULL; }
// call the alarm func void uwsgi_alarm_run(struct uwsgi_alarm_instance *uai, char *msg, size_t len) { time_t now = uwsgi_now(); // avoid alarm storming/loop if last message is the same if (!uwsgi_strncmp(msg, len, uai->last_msg, uai->last_msg_size)) { if (now - uai->last_run < uwsgi.alarm_freq) return; } uai->alarm->func(uai, msg, len); uai->last_run = uwsgi_now(); memcpy(uai->last_msg, msg, len); uai->last_msg_size = len; }
static char *uwsgi_ssi_get_arg(struct uwsgi_ssi_arg *argv, int argc, char *key, size_t key_len, size_t *val_len) { int i; for(i=0;i<argc;i++) { struct uwsgi_ssi_arg *arg = &argv[i]; if (!uwsgi_strncmp(arg->key, arg->key_len, key, key_len)) { *val_len = arg->val_len; return arg->value; } } return NULL; }
char *uwsgi_get_mime_type(char *name, int namelen, size_t *size) { int i; int count = 0; char *ext = NULL; for (i = namelen - 1; i >= 0; i--) { if (!isalnum((int) name[i])) { if (name[i] == '.') { ext = name + (namelen - count); break; } } count++; } if (!ext) return NULL; struct uwsgi_dyn_dict *udd = uwsgi.mimetypes; while (udd) { if (!uwsgi_strncmp(ext, count, udd->key, udd->keylen)) { udd->hits++; // auto optimization if (udd->prev) { if (udd->hits > udd->prev->hits) { struct uwsgi_dyn_dict *udd_parent = udd->prev->prev, *udd_prev = udd->prev; if (udd_parent) { udd_parent->next = udd; } if (udd->next) { udd->next->prev = udd_prev; } udd_prev->prev = udd; udd_prev->next = udd->next; udd->prev = udd_parent; udd->next = udd_prev; if (udd->prev == NULL) { uwsgi.mimetypes = udd; } } } *size = udd->vallen; return udd->value; } udd = udd->next; } return NULL; }
static int uwsgi_sni_cb(SSL *ssl, int *ad, void *arg) { const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); if (!servername) return SSL_TLSEXT_ERR_NOACK; size_t servername_len = strlen(servername); struct uwsgi_string_list *usl = uwsgi.sni; while(usl) { if (!uwsgi_strncmp(usl->value, usl->len, (char *)servername, servername_len)) { SSL_set_SSL_CTX(ssl, usl->custom_ptr); return SSL_TLSEXT_ERR_OK; } usl = usl->next; } #ifdef UWSGI_PCRE struct uwsgi_regexp_list *url = uwsgi.sni_regexp; while(url) { if (uwsgi_regexp_match(url->pattern, url->pattern_extra, (char *)servername, servername_len) >= 0) { SSL_set_SSL_CTX(ssl, url->custom_ptr); return SSL_TLSEXT_ERR_OK; } url = url->next; } #endif if (uwsgi.sni_dir) { size_t sni_dir_len = strlen(uwsgi.sni_dir); char *sni_dir_cert = uwsgi_concat4n(uwsgi.sni_dir, sni_dir_len, "/", 1, (char *) servername, servername_len, ".crt", 4); char *sni_dir_key = uwsgi_concat4n(uwsgi.sni_dir, sni_dir_len, "/", 1, (char *) servername, servername_len, ".key", 4); char *sni_dir_client_ca = uwsgi_concat4n(uwsgi.sni_dir, sni_dir_len, "/", 1, (char *) servername, servername_len, ".ca", 3); if (uwsgi_file_exists(sni_dir_cert) && uwsgi_file_exists(sni_dir_key)) { char *client_ca = NULL; if (uwsgi_file_exists(sni_dir_client_ca)) { client_ca = sni_dir_client_ca; } usl = uwsgi_ssl_add_sni_item(uwsgi_str((char *)servername), sni_dir_cert, sni_dir_key, uwsgi.sni_dir_ciphers, client_ca); if (!usl) goto done; free(sni_dir_cert); free(sni_dir_key); free(sni_dir_client_ca); SSL_set_SSL_CTX(ssl, usl->custom_ptr); uwsgi_log("[uwsgi-sni for pid %d] added context for %s\n", (int) getpid(), servername); return SSL_TLSEXT_ERR_OK; } done: free(sni_dir_cert); free(sni_dir_key); free(sni_dir_client_ca); } return SSL_TLSEXT_ERR_NOACK; }
int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t filename_len, struct stat *st) { // check for filename size if (filename_len + 4 > PATH_MAX) return 0; // check for supported encodings if (!uwsgi_contains_n(wsgi_req->encoding, wsgi_req->encoding_len, "gzip", 4) ) return 0; // check for 'all' if (uwsgi.static_gzip_all) goto gzip; // check for dirs/prefix struct uwsgi_string_list *usl = uwsgi.static_gzip_dir; while(usl) { if (!uwsgi_starts_with(filename, filename_len, usl->value, usl->len)) { goto gzip; } usl = usl->next; } // check for ext/suffix usl = uwsgi.static_gzip_ext; while(usl) { if (!uwsgi_strncmp(filename + (filename_len - usl->len), usl->len, usl->value, usl->len)) { goto gzip; } usl = usl->next; } #ifdef UWSGI_PCRE // check for regexp struct uwsgi_regexp_list *url = uwsgi.static_gzip; while(url) { if (uwsgi_regexp_match(url->pattern, url->pattern_extra, filename, filename_len) >= 0) { goto gzip; } url = url->next; } #endif return 0; gzip: memcpy(filename + filename_len, ".gz\0", 4); filename_len += 3; if (stat(filename, st)) { filename_len -= 3; filename[filename_len] = 0; return 0; } return 1; }
struct uwsgi_spooler *uwsgi_get_spooler_by_name(char *name, size_t name_len) { struct uwsgi_spooler *uspool = uwsgi.spoolers; while (uspool) { if (!uwsgi_strncmp(uspool->dir, strlen(uspool->dir), name, name_len)) { return uspool; } uspool = uspool->next; } return NULL; }
static void spooler_req_parser_hook(char *key, uint16_t key_len, char *value, uint16_t value_len, void *data) { struct spooler_req *sr = (struct spooler_req *) data; if (!uwsgi_strncmp(key, key_len, "spooler", 7)) { sr->spooler = value; sr->spooler_len = value_len; return; } if (!uwsgi_strncmp(key, key_len, "priority", 8)) { sr->priority = value; sr->priority_len = value_len; return; } if (!uwsgi_strncmp(key, key_len, "at", 2)) { // at can be a float... char *dot = memchr(value, '.', value_len); if (dot) { value_len = dot - value; } sr->at = uwsgi_str_num(value, value_len); return; } }
static char *check_qs(char *qs, uint16_t qs_len, char *key, uint16_t keylen, uint16_t *vallen) { // search for the equal sign char *equal = memchr(qs, '=', qs_len); if (!equal) return NULL; if (uwsgi_strncmp(key, keylen, qs, equal-qs)) { return NULL; } qs_len -= (equal-qs)+1; if (qs_len == 0) return NULL; *vallen = qs_len; return equal+1; }
struct uwsgi_subscribe_node *uwsgi_get_subscribe_node_by_name(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen, char *val, uint16_t vallen) { if (keylen > 0xff) return NULL; struct uwsgi_subscribe_slot *current_slot = uwsgi_get_subscribe_slot(slot, key, keylen); if (current_slot) { struct uwsgi_subscribe_node *node = current_slot->nodes; while (node) { if (!uwsgi_strncmp(val, vallen, node->name, node->len)) { return node; } node = node->next; } } return NULL; }
static uint16_t htpasswd_check(char *filename, char *auth) { char line[1024]; char *colon = strchr(auth, ':'); if (!colon) return 0; FILE *htpasswd = fopen(filename, "r"); if (!htpasswd) { return 0; } while(fgets(line, 1024, htpasswd)) { char *colon2 = strchr(line, ':'); if (!colon2) break; char *cpwd = colon2+1; size_t clen = strlen(cpwd); if (clen < 13) break; if (clen > 13) cpwd[13] = 0; #ifdef __linux__ struct crypt_data cd; cd.initialized = 0; // we do as nginx here cd.current_salt[0] = ~cpwd[0]; char *crypted = crypt_r( colon+1, cpwd, &cd); #else if (uwsgi.threads > 1) pthread_mutex_lock(&ur_basicauth_crypt_mutex); char *crypted = crypt( colon+1, cpwd); if (uwsgi.threads > 1) pthread_mutex_unlock(&ur_basicauth_crypt_mutex); #endif if (!crypted) continue; if (!strcmp( crypted, cpwd )) { if (!uwsgi_strncmp(auth, colon-auth, line, colon2-line)) { fclose(htpasswd); return colon-auth; } } } fclose(htpasswd); return 0; }
static char *uwsgi_cgi_get_helper(char *filename) { struct uwsgi_dyn_dict *helpers = uc.helpers; size_t len = strlen(filename); while(helpers) { if (len >= (size_t) helpers->keylen) { if (!uwsgi_strncmp((filename+len)-helpers->keylen, helpers->keylen, helpers->key, helpers->keylen)) { return helpers->value; } } helpers = helpers->next; } return NULL; }
static char *check_cookie(char *cookie, uint16_t cookie_len, char *key, uint16_t keylen, uint16_t *vallen) { uint16_t orig_cookie_len = cookie_len-1; // first lstrip white spaces char *ptr = cookie; uint16_t i; for(i=0;i<cookie_len;i++) { if (isspace((int)ptr[i])) { cookie++; cookie_len--; } else { break; } } // then rstrip (skipping the first char...) for(i=orig_cookie_len;i>0;i--) { if (isspace((int)ptr[i])) { cookie_len--; } else { break; } } // now search for the first equal sign char *equal = memchr(cookie, '=', cookie_len); if (!equal) return NULL; if (uwsgi_strncmp(key, keylen, cookie, equal-cookie)) { return NULL; } cookie_len -= (equal-cookie)+1; if (cookie_len == 0) return NULL; *vallen = cookie_len; return equal+1; }
void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) { struct uwsgi_logchunk *logchunk = uwsgi.logchunks; if (logchunk) { while(logchunk) { if (!logchunk->next) { logchunk->next = uwsgi_calloc(sizeof(struct uwsgi_logchunk)); logchunk = logchunk->next; break; } logchunk = logchunk->next; } } else { uwsgi.logchunks = uwsgi_calloc(sizeof(struct uwsgi_logchunk)); logchunk = uwsgi.logchunks; } /* 0 -> raw test 1 -> offsetof variable 2 -> logvar 3 -> func */ logchunk->type = variable; logchunk->vec = pos; // normal text logchunk->ptr = ptr; logchunk->len = len; // variable if (variable) { if (!uwsgi_strncmp(ptr, len, "uri", 3)) { logchunk->pos = offsetof(struct wsgi_request, uri); logchunk->pos_len = offsetof(struct wsgi_request, uri_len); } else if (!uwsgi_strncmp(ptr, len, "method", 6)) {
// this is the command manager static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues) { int64_t more = 0; size_t more_size = sizeof(more); int i; zmq_msg_t msg[6]; zmq_msg_init(&msg[0]); zmq_msg_init(&msg[1]); zmq_msg_init(&msg[2]); zmq_msg_init(&msg[3]); zmq_msg_init(&msg[4]); zmq_msg_init(&msg[5]); for(i=0;i<6;i++) { #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0) zmq_recvmsg(ues->data, &msg[i], ZMQ_DONTWAIT); #else zmq_recv(ues->data, &msg[i], ZMQ_NOBLOCK); #endif if (zmq_getsockopt(ues->data, ZMQ_RCVMORE, &more, &more_size)) { uwsgi_error("zmq_getsockopt()"); break; } if (!more && i < 4) break; } if (i < 1) { uwsgi_log("[emperor-zeromq] bad message received (command and instance name required)\n"); return; } char *ez_cmd = zmq_msg_data(&msg[0]); size_t ez_cmd_len = zmq_msg_size(&msg[0]); char *ez_name = zmq_msg_data(&msg[1]); size_t ez_name_len = zmq_msg_size(&msg[1]); char *ez_config = NULL; size_t ez_config_len = 0; char *ez_uid = NULL; size_t ez_uid_len = 0; char *ez_gid = NULL; size_t ez_gid_len = 0; char *ez_socket_name = NULL; size_t ez_socket_name_len = 0; char *socket_name = NULL; // config if (i > 1) { ez_config = zmq_msg_data(&msg[2]); ez_config_len = zmq_msg_size(&msg[2]); } // uid if (i > 2) { ez_uid = zmq_msg_data(&msg[3]); ez_uid_len = zmq_msg_size(&msg[3]); } // gid if (i > 3) { ez_gid = zmq_msg_data(&msg[4]); ez_gid_len = zmq_msg_size(&msg[4]); } // gid if (i > 4) { ez_socket_name = zmq_msg_data(&msg[5]); ez_socket_name_len = zmq_msg_size(&msg[5]); } char *name = uwsgi_concat2n(ez_name, ez_name_len, "", 0); // ok let's start checking commands if (!uwsgi_strncmp(ez_cmd, ez_cmd_len, "touch", 5)) { char *config = NULL; if (ez_config_len > 0) { config = uwsgi_concat2n(ez_config, ez_config_len, "", 0); } uid_t vassal_uid = 0; gid_t vassal_gid = 0; if (ez_uid_len > 0) { vassal_uid = uwsgi_str_num(ez_uid, ez_uid_len); } if (ez_gid_len > 0) { vassal_gid = uwsgi_str_num(ez_gid, ez_gid_len); } if (ez_socket_name) { socket_name = uwsgi_concat2n(ez_socket_name, ez_socket_name_len, "", 0); } uwsgi_emperor_simple_do(ues, name, config, uwsgi_now(), vassal_uid, vassal_gid, socket_name); if (config) { free(config); } if (socket_name) { free(socket_name); } } // destroy an instance else if (!uwsgi_strncmp(ez_cmd, ez_cmd_len, "destroy", 7)) { struct uwsgi_instance *ui = emperor_get(name); if (!ui) { uwsgi_log("[emperor-zeromq] unknown instance \"%s\"\n", name); } else { emperor_stop(ui); } } else { uwsgi_log("[emperor-zeromq] unknown command \"%.*s\"\n", (int)ez_cmd_len, ez_cmd); } free(name); zmq_msg_close(&msg[0]); zmq_msg_close(&msg[1]); zmq_msg_close(&msg[2]); zmq_msg_close(&msg[3]); zmq_msg_close(&msg[4]); zmq_msg_close(&msg[5]); }
static int uwsgi_glusterfs_request(struct wsgi_request *wsgi_req) { char filename[PATH_MAX+1]; /* Standard GlusterFS request */ if (!wsgi_req->uh->pktsize) { uwsgi_log( "Empty GlusterFS request. skip.\n"); return -1; } if (uwsgi_parse_vars(wsgi_req)) { return -1; } // blocks empty paths if (wsgi_req->path_info_len == 0 || wsgi_req->path_info_len > PATH_MAX) { uwsgi_403(wsgi_req); return UWSGI_OK; } wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, glusterfs_plugin.modifier1); if (wsgi_req->app_id == -1 && !uwsgi.no_default_app && uwsgi.default_app > -1) { if (uwsgi_apps[uwsgi.default_app].modifier1 == glusterfs_plugin.modifier1) { wsgi_req->app_id = uwsgi.default_app; } } if (wsgi_req->app_id == -1) { uwsgi_404(wsgi_req); return UWSGI_OK; } struct uwsgi_app *ua = &uwsgi_apps[wsgi_req->app_id]; memcpy(filename, wsgi_req->path_info, wsgi_req->path_info_len); filename[wsgi_req->path_info_len] = 0; glfs_fd_t *fd = glfs_open((glfs_t *) ua->interpreter, filename, O_RDONLY); if (!fd) { uwsgi_404(wsgi_req); return UWSGI_OK; } struct stat st; if (glfs_fstat(fd, &st)) { uwsgi_403(wsgi_req); return UWSGI_OK; } if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto end; size_t mime_type_len = 0; char *mime_type = uwsgi_get_mime_type(wsgi_req->path_info, wsgi_req->path_info_len, &mime_type_len); if (mime_type) { if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_len)) goto end; } if (uwsgi_response_add_last_modified(wsgi_req, (uint64_t) st.st_mtime)) goto end; if (uwsgi_response_add_content_length(wsgi_req, st.st_size)) goto end; // skip body on HEAD if (uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) { size_t remains = st.st_size; while(remains > 0) { char buf[8192]; ssize_t rlen = glfs_read (fd, buf, UMIN(remains, 8192), 0); if (rlen <= 0) goto end; if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) goto end; remains -= rlen; } } end: glfs_close(fd); return UWSGI_OK; }
// dumb/fake tnetstring implementation...all is a string static int uwsgi_mongrel2_tnetstring_parse(struct wsgi_request *wsgi_req, char *buf, int len) { char *ptr = buf; char *watermark = buf + len; char *key = NULL; size_t keylen = 0; char *val = NULL; size_t vallen = 0; uint16_t script_name_len = 0; char *query_string = NULL; uint16_t query_string_len = 0; int async_upload = 0; // set an empty SCRIPT_NAME wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SCRIPT_NAME", 11, "", 0); while (ptr < watermark) { ptr = uwsgi_netstring(ptr, len - (ptr - buf), &key, &keylen); if (ptr == NULL) break; // empty keys are not allowed if (keylen == 0) break; if (ptr >= watermark) break; ptr = uwsgi_netstring(ptr, len - (ptr - buf), &val, &vallen); if (ptr == NULL) break; if (key[0] < 97) { if (!uwsgi_strncmp("METHOD", 6, key, keylen)) { if (!uwsgi_strncmp("JSON", 4, val, vallen)) { return -1; } wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REQUEST_METHOD", 14, val, vallen); } else if (!uwsgi_strncmp("VERSION", 7, key, keylen)) { wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PROTOCOL", 15, val, vallen); } else if (!uwsgi_strncmp("QUERY", 5, key, keylen)) { wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "QUERY_STRING", 12, val, vallen); query_string = val; query_string_len = vallen; } else if (!uwsgi_strncmp("PATH", 4, key, keylen)) { wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "PATH_INFO", 9, val + script_name_len, vallen - script_name_len); if (query_string_len) { char *request_uri = uwsgi_concat3n(val, vallen, "?", 1, query_string, query_string_len); wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REQUEST_URI", 11, request_uri, vallen + 1 + query_string_len); free(request_uri); } else { wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REQUEST_URI", 11, val, vallen); } } } else { // add header if (!uwsgi_strncmp("host", 4, key, keylen)) { char *colon = memchr(val, ':', vallen); if (colon) { wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, colon + 1, vallen - ((colon + 1) - val)); } else { wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, "80", 2); } } else if (!uwsgi_strncmp("content-length", 14, key, keylen)) { wsgi_req->post_cl = uwsgi_str_num(val, vallen); } else if (!uwsgi_strncmp("x-mongrel2-upload-done", 22, key, keylen)) { char *post_filename = uwsgi_concat2n(val, vallen, "", 0); wsgi_req->post_file = fopen(post_filename, "r"); if (!wsgi_req->post_file) { uwsgi_error_open(post_filename); wsgi_req->do_not_log = 1; } async_upload += 2; free(post_filename); } else if (!uwsgi_strncmp("x-forwarded-for", 15, key, keylen)) { char *colon = memchr(val, ',', vallen); if (colon) { wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, colon + 1, (colon + 1) - val); } else { wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, val, vallen); } } else if (!uwsgi_strncmp("x-mongrel2-upload-start", 23, key, keylen)) { async_upload += 1; } wsgi_req->uh->pktsize += proto_base_add_uwsgi_header(wsgi_req, key, keylen, val, vallen); } } wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_NAME", 11, uwsgi.hostname, uwsgi.hostname_len); if (query_string == NULL) { // always set QUERY_STRING wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "QUERY_STRING", 12, "", 0); } // reject uncomplete upload if (async_upload == 1) { return -1; } return 0; }
static int uwsgi_webdav_request(struct wsgi_request *wsgi_req) { if (!udav.mountpoints) { uwsgi_500(wsgi_req); return -1; } if (uwsgi_parse_vars(wsgi_req)) { return -1; } if (wsgi_req->path_info_len == 0) { uwsgi_403(wsgi_req); return UWSGI_OK; } wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, webdav_plugin.modifier1); if (wsgi_req->app_id == -1) { uwsgi_403(wsgi_req); return UWSGI_OK; } // non lockables methods... if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "OPTIONS", 7)) { return uwsgi_wevdav_manage_options(wsgi_req); } if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "GET", 3)) { return uwsgi_wevdav_manage_get(wsgi_req, 1); } if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) { return uwsgi_wevdav_manage_get(wsgi_req, 0); } if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "PROPFIND", 8)) { if (wsgi_req->post_cl > 0) { ssize_t body_len = 0; char *body = uwsgi_request_body_read(wsgi_req, wsgi_req->post_cl, &body_len); #ifdef UWSGI_DEBUG uwsgi_log("%.*s\n", body_len, body); #endif xmlDoc *doc = xmlReadMemory(body, body_len, NULL, NULL, 0); if (!doc) goto end; uwsgi_wevdav_manage_propfind(wsgi_req, doc); xmlFreeDoc(doc); } else { uwsgi_wevdav_manage_propfind(wsgi_req, NULL); } } if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "REPORT", 6)) { if (wsgi_req->post_cl > 0) { ssize_t body_len = 0; char *body = uwsgi_request_body_read(wsgi_req, wsgi_req->post_cl, &body_len); #ifdef UWSGI_DEBUG uwsgi_log("%.*s\n", body_len, body); #endif xmlDoc *doc = xmlReadMemory(body, body_len, NULL, NULL, 0); if (!doc) goto end; xmlFreeDoc(doc); } } // lockable methods ... // check for locking if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "PUT", 3)) { return uwsgi_wevdav_manage_put(wsgi_req); } if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "DELETE", 6)) { return uwsgi_wevdav_manage_delete(wsgi_req); } if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "MKCOL", 5)) { return uwsgi_wevdav_manage_mkcol(wsgi_req); } if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "MKCALENDAR", 10)) { if (wsgi_req->post_cl == 0) goto end; ssize_t body_len = 0; char *body = uwsgi_request_body_read(wsgi_req, wsgi_req->post_cl, &body_len); #ifdef UWSGI_DEBUG uwsgi_log("%.*s\n", body_len, body); #endif xmlDoc *doc = xmlReadMemory(body, body_len, NULL, NULL, 0); if (!doc) goto end; uwsgi_wevdav_manage_mkcalendar(wsgi_req, doc); xmlFreeDoc(doc); } if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "COPY", 4)) { return uwsgi_wevdav_manage_copy(wsgi_req); } if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "MOVE", 4)) { return uwsgi_wevdav_manage_move(wsgi_req); } if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "LOCK", 4)) { if (wsgi_req->post_cl > 0) { ssize_t body_len = 0; char *body = uwsgi_request_body_read(wsgi_req, wsgi_req->post_cl, &body_len); #ifdef UWSGI_DEBUG uwsgi_log("%.*s\n", body_len, body); #endif xmlDoc *doc = xmlReadMemory(body, body_len, NULL, NULL, 0); if (!doc) goto end; xmlFreeDoc(doc); } return uwsgi_wevdav_manage_lock(wsgi_req); } if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "PROPPATCH", 9)) { if (wsgi_req->post_cl == 0) goto end; ssize_t body_len = 0; char *body = uwsgi_request_body_read(wsgi_req, wsgi_req->post_cl, &body_len); #ifdef UWSGI_DEBUG uwsgi_log("%.*s\n", body_len, body); #endif xmlDoc *doc = xmlReadMemory(body, body_len, NULL, NULL, 0); if (!doc) goto end; uwsgi_wevdav_manage_proppatch(wsgi_req, doc); xmlFreeDoc(doc); } end: return UWSGI_OK; }
struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi_subscribe_req *usr) { struct uwsgi_subscribe_slot *current_slot = uwsgi_get_subscribe_slot(slot, usr->key, usr->keylen), *old_slot = NULL, *a_slot; struct uwsgi_subscribe_node *node, *old_node = NULL; if (usr->address_len > 0xff || usr->address_len == 0) return NULL; #ifdef UWSGI_SSL if (uwsgi.subscriptions_sign_check_dir) { if (usr->sign_len == 0 || usr->base_len == 0) return NULL; } #endif if (current_slot) { #ifdef UWSGI_SSL if (uwsgi.subscriptions_sign_check_dir && !uwsgi_subscription_sign_check(current_slot, usr)) { return NULL; } #endif node = current_slot->nodes; while (node) { if (!uwsgi_strncmp(node->name, node->len, usr->address, usr->address_len)) { #ifdef UWSGI_SSL // this should avoid sending sniffed packets... if (uwsgi.subscriptions_sign_check_dir && usr->unix_check <= node->unix_check) { uwsgi_log("[uwsgi-subscription for pid %d] invalid (sniffed ?) packet sent for slot: %.*s node: %.*s unix_check: %lu\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address, (unsigned long) usr->unix_check); return NULL; } #endif // remove death mark and update cores and load node->death_mark = 0; node->last_check = uwsgi_now(); node->cores = usr->cores; node->load = usr->load; node->weight = usr->weight; if (!node->weight) node->weight = 1; node->last_requests = 0; return node; } old_node = node; node = node->next; } #ifdef UWSGI_SSL if (uwsgi.subscriptions_sign_check_dir && usr->unix_check < (uwsgi_now() - (time_t) uwsgi.subscriptions_sign_check_tolerance)) { uwsgi_log("[uwsgi-subscription for pid %d] invalid (sniffed ?) packet sent for slot: %.*s node: %.*s unix_check: %lu\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address, (unsigned long) usr->unix_check); return NULL; } #endif node = uwsgi_malloc(sizeof(struct uwsgi_subscribe_node)); node->len = usr->address_len; node->modifier1 = usr->modifier1; node->modifier2 = usr->modifier2; node->requests = 0; node->last_requests = 0; node->transferred = 0; node->reference = 0; node->death_mark = 0; node->failcnt = 0; node->cores = usr->cores; node->load = usr->load; node->weight = usr->weight; node->unix_check = usr->unix_check; if (!node->weight) node->weight = 1; node->wrr = 0; node->last_check = uwsgi_now(); node->slot = current_slot; memcpy(node->name, usr->address, usr->address_len); if (old_node) { old_node->next = node; } node->next = NULL; uwsgi_log("[uwsgi-subscription for pid %d] %.*s => new node: %.*s\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address); return node; } else { #ifdef UWSGI_SSL FILE *kf = NULL; if (uwsgi.subscriptions_sign_check_dir) { if (usr->unix_check < (uwsgi_now() - (time_t) uwsgi.subscriptions_sign_check_tolerance)) { uwsgi_log("[uwsgi-subscription for pid %d] invalid (sniffed ?) packet sent for slot: %.*s node: %.*s unix_check: %lu\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address, (unsigned long) usr->unix_check); return NULL; } char *keyfile = uwsgi_sanitize_cert_filename(uwsgi.subscriptions_sign_check_dir, usr->key, usr->keylen); kf = fopen(keyfile, "r"); free(keyfile); if (!kf) return NULL; } #endif current_slot = uwsgi_malloc(sizeof(struct uwsgi_subscribe_slot)); uint32_t hash = djb33x_hash(usr->key, usr->keylen); int hash_key = hash % 0xffff; current_slot->hash = hash_key; #ifdef UWSGI_SSL if (uwsgi.subscriptions_sign_check_dir) { current_slot->sign_public_key = PEM_read_PUBKEY(kf, NULL, NULL, NULL); fclose(kf); if (!current_slot->sign_public_key) { uwsgi_log("unable to load public key for %.*s\n", usr->keylen, usr->key); free(current_slot); return NULL; } current_slot->sign_ctx = EVP_MD_CTX_create(); if (!current_slot->sign_ctx) { uwsgi_log("unable to initialize EVP context for %.*s\n", usr->keylen, usr->key); EVP_PKEY_free(current_slot->sign_public_key); free(current_slot); return NULL; } if (!uwsgi_subscription_sign_check(current_slot, usr)) { EVP_PKEY_free(current_slot->sign_public_key); EVP_MD_CTX_destroy(current_slot->sign_ctx); free(current_slot); return NULL; } } #endif current_slot->keylen = usr->keylen; memcpy(current_slot->key, usr->key, usr->keylen); current_slot->key[usr->keylen] = 0; current_slot->hits = 0; current_slot->nodes = uwsgi_malloc(sizeof(struct uwsgi_subscribe_node)); current_slot->nodes->slot = current_slot; current_slot->nodes->len = usr->address_len; current_slot->nodes->reference = 0; current_slot->nodes->requests = 0; current_slot->nodes->last_requests = 0; current_slot->nodes->transferred = 0; current_slot->nodes->death_mark = 0; current_slot->nodes->failcnt = 0; current_slot->nodes->modifier1 = usr->modifier1; current_slot->nodes->modifier2 = usr->modifier2; current_slot->nodes->cores = usr->cores; current_slot->nodes->load = usr->load; current_slot->nodes->weight = usr->weight; current_slot->nodes->unix_check = usr->unix_check; if (!current_slot->nodes->weight) current_slot->nodes->weight = 1; current_slot->nodes->wrr = 0; memcpy(current_slot->nodes->name, usr->address, usr->address_len); current_slot->nodes->last_check = uwsgi_now(); current_slot->nodes->next = NULL; a_slot = slot[hash_key]; while (a_slot) { old_slot = a_slot; a_slot = a_slot->next; } if (old_slot) { old_slot->next = current_slot; } current_slot->prev = old_slot; current_slot->next = NULL; if (!slot[hash_key] || current_slot->prev == NULL) { slot[hash_key] = current_slot; } uwsgi_log("[uwsgi-subscription for pid %d] new pool: %.*s (hash key: %d)\n", (int) uwsgi.mypid, usr->keylen, usr->key, current_slot->hash); uwsgi_log("[uwsgi-subscription for pid %d] %.*s => new node: %.*s\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address); return current_slot->nodes; } }