/* Hiawatha | envir.c */ #include "config.h" #include #include #include "alternative.h" #include "envir.h" #include "libip.h" #include "session.h" #define SSL_VAR_SIZE 512 static int add_to_environment(t_fcgi_buffer *fcgi_buffer, char *key, char *value) { char buffer[8]; int len; size_t key_len, value_len; if (fcgi_buffer == NULL) { /* Normal CGI */ setenv(key, value, 1); } else { /* FastCGI */ key_len = strlen(key); value_len = strlen(value); if (value_len <= 127) { *buffer = (unsigned char)key_len; len = 1; } else { *(buffer) = (unsigned char)((key_len >> 24) | 0x80); *(buffer + 1) = (unsigned char)((key_len >> 16) & 0xff); *(buffer + 2) = (unsigned char)((key_len >> 8) & 0xff); *(buffer + 3) = (unsigned char)(key_len & 0xff); len = 4; } if (value_len <= 127) { *(buffer + len) = (unsigned char)value_len; len++; } else { *(buffer + len) = (unsigned char)((value_len >> 24) | 0x80); *(buffer + len + 1) = (unsigned char)((value_len >> 16) & 0xff); *(buffer + len + 2) = (unsigned char)((value_len >> 8) & 0xff); *(buffer + len + 3) = (unsigned char)(value_len & 0xff); len += 4; } if (send_fcgi_buffer(fcgi_buffer, buffer, len) == -1) { return -1; } else if (send_fcgi_buffer(fcgi_buffer, key, key_len) == -1) { return -1; } else if (send_fcgi_buffer(fcgi_buffer, value, value_len) == -1) { return -1; } } return 0; } static int add_to_environment_chroot(t_session *session, t_fcgi_buffer *fcgi_buffer, char *key, char *value) { size_t ofs = 0; char c; if (session->fcgi_server != NULL) { if (strncmp(value, session->fcgi_server->chroot, session->fcgi_server->chroot_len) == 0) { c = value[session->fcgi_server->chroot_len]; if ((c == '/') || (c == '\0')) { ofs = session->fcgi_server->chroot_len; } } } return add_to_environment(fcgi_buffer, key, value + ofs); } /* Copy a headerfield to an environment setting */ static int headerfield_to_environment(t_session *session, t_fcgi_buffer *fcgi_buffer, char *key, char *envir) { char *value; if ((value = get_headerfield(key, session->headerfields)) != NULL) { return add_to_environment(fcgi_buffer, envir, value); } else { return 0; } } /* Set environment variables for CGI script. */ void set_environment(t_session *session, t_fcgi_buffer *fcgi_buffer) { char ip[MAX_IP_STR_LEN], len[20], value[10], *name; size_t len1, len2; t_keyvalue *envir; #ifdef HAVE_SSL char subject[SSL_VAR_SIZE + 1], issuer[SSL_VAR_SIZE + 1]; #endif #ifdef CYGWIN char *root; #endif add_to_environment(fcgi_buffer, "GATEWAY_INTERFACE", "CGI/1.1"); add_to_environment(fcgi_buffer, "REQUEST_METHOD", session->method); add_to_environment(fcgi_buffer, "REQUEST_URI", session->uri); if (session->uri[session->uri_len - 1] == '/') { len1 = session->uri_len; len2 = strlen(session->host->start_file); if ((name = (char*)malloc(len1 + len2 + 1)) != NULL) { memcpy(name, session->uri, len1); memcpy(name + len1, session->host->start_file, len2); name[len1 + len2] = '\0'; add_to_environment(fcgi_buffer, "SCRIPT_NAME", name); free(name); } } else { add_to_environment(fcgi_buffer, "SCRIPT_NAME", session->uri); } #ifdef HAVE_REWRITE add_to_environment(fcgi_buffer, "SCRIPT_URL", session->script_url); #endif add_to_environment_chroot(session, fcgi_buffer, "SCRIPT_FILENAME", session->file_on_disk); #ifdef CYGWIN if (session->config->platform == windows) { if ((root = strdup(session->host->website_root)) != NULL) { add_to_environment_chroot(session, fcgi_buffer, "DOCUMENT_ROOT", cygwin_to_windows(root)); free(root); } } else #endif add_to_environment_chroot(session, fcgi_buffer, "DOCUMENT_ROOT", session->host->website_root); if (inet_ntop(session->ip_address.family, &(session->ip_address.value), ip, MAX_IP_STR_LEN) == NULL) { strcpy(ip, "?.?.?.?"); } add_to_environment(fcgi_buffer, "REMOTE_ADDR", ip); if (session->vars != NULL) { add_to_environment(fcgi_buffer, "QUERY_STRING", session->vars); } if (session->body != NULL) { len[19] = '\0'; snprintf(len, 19, "%ld", session->content_length); add_to_environment(fcgi_buffer, "CONTENT_LENGTH", len); headerfield_to_environment(session, fcgi_buffer, "Content-Type:", "CONTENT_TYPE"); } value[9] = '\0'; snprintf(value, 9, "%d", session->binding->port); add_to_environment(fcgi_buffer, "SERVER_PORT", value); add_to_environment(fcgi_buffer, "SERVER_NAME", *(session->host->hostname.item)); add_to_environment(fcgi_buffer, "SERVER_PROTOCOL", session->http_version); add_to_environment(fcgi_buffer, "SERVER_SOFTWARE", "Hiawatha v"VERSION); if (session->binding->binding_id != NULL) { add_to_environment(fcgi_buffer, "SERVER_BINDING", session->binding->binding_id); } add_to_environment(fcgi_buffer, "REDIRECT_STATUS", "200"); if (session->remote_user != NULL) { add_to_environment(fcgi_buffer, "AUTH_TYPE", "Basic"); add_to_environment(fcgi_buffer, "REMOTE_USER", session->remote_user); } #ifdef HAVE_SSL if (session->binding->use_ssl) { add_to_environment(fcgi_buffer, "HTTP_SCHEME", "https"); } else #endif add_to_environment(fcgi_buffer, "HTTP_SCHEME", "http"); headerfield_to_environment(session, fcgi_buffer, "Accept:", "HTTP_ACCEPT"); headerfield_to_environment(session, fcgi_buffer, "Accept-Charset:", "HTTP_ACCEPT_CHARSET"); headerfield_to_environment(session, fcgi_buffer, "Accept-Language:", "HTTP_ACCEPT_LANGUAGE"); headerfield_to_environment(session, fcgi_buffer, "Client-IP:", "HTTP_CLIENT_IP"); headerfield_to_environment(session, fcgi_buffer, "From:", "HTTP_FROM"); headerfield_to_environment(session, fcgi_buffer, "Host:", "HTTP_HOST"); headerfield_to_environment(session, fcgi_buffer, "Range:", "HTTP_RANGE"); headerfield_to_environment(session, fcgi_buffer, "Referer:", "HTTP_REFERER"); headerfield_to_environment(session, fcgi_buffer, "User-Agent:", "HTTP_USER_AGENT"); headerfield_to_environment(session, fcgi_buffer, "Via:", "HTTP_VIA"); headerfield_to_environment(session, fcgi_buffer, "X-Forwarded-For:", "HTTP_X_FORWARDED_FOR"); if (session->path_info != NULL) { add_to_environment(fcgi_buffer, "PATH_INFO", session->path_info); } snprintf(value, 9, "%d", session->return_code); add_to_environment(fcgi_buffer, "HTTP_RETURN_CODE", value); if (session->error_code != -1) { snprintf(value, 9, "%d", session->error_code); add_to_environment(fcgi_buffer, "HTTP_GENERATED_ERROR", value); } if (session->cookie != NULL) { add_to_environment(fcgi_buffer, "HTTP_COOKIE", session->cookie); } else { headerfield_to_environment(session, fcgi_buffer, "Cookie:", "HTTP_COOKIE"); } envir = session->host->envir_str; while (envir != NULL) { if (strncmp(envir->key, "CGIWRAP_", 8) != 0) { add_to_environment(fcgi_buffer, envir->key, envir->value); } envir = envir->next; } #ifdef HAVE_SSL if (session->binding->use_ssl) { if (get_client_certificate(session->ssl_data, SSL_VAR_SIZE, subject, issuer) == 0) { add_to_environment(fcgi_buffer, "SSL_CLIENT_SUBJECT", subject); add_to_environment(fcgi_buffer, "SSL_CLIENT_ISSUER", issuer); } } #endif }