Welcome! Log In Create A New Profile

Advanced

[nginx] svn commit: r4674 - trunk/src/os/win32

Anonymous User
June 05, 2012 09:38AM
Author: mdounin
Date: 2012-06-05 13:36:09 +0000 (Tue, 05 Jun 2012)
New Revision: 4674
URL: http://trac.nginx.org/nginx/changeset/4674/nginx

Log:
Win32: disallowed access to various non-canonical name variants.

This includes trailings dots and spaces, NTFS streams (and short names, as
previously checked). The checks are now also done in ngx_file_info(), thus
allowing to use the "try_files" directive to protect external scripts.


Modified:
trunk/src/os/win32/ngx_files.c

Modified: trunk/src/os/win32/ngx_files.c
===================================================================
--- trunk/src/os/win32/ngx_files.c 2012-06-05 13:17:05 UTC (rev 4673)
+++ trunk/src/os/win32/ngx_files.c 2012-06-05 13:36:09 UTC (rev 4674)
@@ -11,6 +11,8 @@

#define NGX_UTF16_BUFLEN 256

+static ngx_int_t ngx_win32_check_filename(u_char *name, u_short *u,
+ size_t len);
static u_short *ngx_utf8_to_utf16(u_short *utf16, u_char *utf8, size_t *len);


@@ -20,8 +22,7 @@
ngx_open_file(u_char *name, u_long mode, u_long create, u_long access)
{
size_t len;
- u_long n;
- u_short *u, *lu;
+ u_short *u;
ngx_fd_t fd;
ngx_err_t err;
u_short utf16[NGX_UTF16_BUFLEN];
@@ -34,25 +35,11 @@
}

fd = INVALID_HANDLE_VALUE;
- lu = NULL;

- if (create == NGX_FILE_OPEN) {
-
- lu = malloc(len * 2);
- if (lu == NULL) {
- goto failed;
- }
-
- n = GetLongPathNameW(u, lu, len);
-
- if (n == 0) {
- goto failed;
- }
-
- if (n != len - 1 || _wcsicmp(u, lu) != 0) {
- ngx_set_errno(NGX_ENOENT);
- goto failed;
- }
+ if (create == NGX_FILE_OPEN
+ && ngx_win32_check_filename(name, u, len) != NGX_OK)
+ {
+ goto failed;
}

fd = CreateFileW(u, mode,
@@ -61,18 +48,12 @@

failed:

- err = ngx_errno;
-
- if (lu) {
- ngx_free(lu);
- }
-
if (u != utf16) {
+ err = ngx_errno;
ngx_free(u);
+ ngx_set_errno(err);
}

- ngx_set_errno(err);
-
return fd;
}

@@ -294,14 +275,14 @@
return NGX_FILE_ERROR;
}

- rc = GetFileAttributesExW(u, GetFileExInfoStandard, &fa);
+ rc = NGX_FILE_ERROR;

- if (u != utf16) {
- err = ngx_errno;
- ngx_free(u);
- ngx_set_errno(err);
+ if (ngx_win32_check_filename(file, u, len) != NGX_OK) {
+ goto failed;
}

+ rc = GetFileAttributesExW(u, GetFileExInfoStandard, &fa);
+
sb->dwFileAttributes = fa.dwFileAttributes;
sb->ftCreationTime = fa.ftCreationTime;
sb->ftLastAccessTime = fa.ftLastAccessTime;
@@ -309,6 +290,14 @@
sb->nFileSizeHigh = fa.nFileSizeHigh;
sb->nFileSizeLow = fa.nFileSizeLow;

+failed:
+
+ if (u != utf16) {
+ err = ngx_errno;
+ ngx_free(u);
+ ngx_set_errno(err);
+ }
+
return rc;
}

@@ -640,6 +629,148 @@
}


+static ngx_int_t
+ngx_win32_check_filename(u_char *name, u_short *u, size_t len)
+{
+ u_char *p, ch;
+ u_long n;
+ u_short *lu;
+ ngx_err_t err;
+ enum {
+ sw_start = 0,
+ sw_normal,
+ sw_after_slash,
+ sw_after_colon,
+ sw_after_dot
+ } state;
+
+ /* check for NTFS streams (":"), trailing dots and spaces */
+
+ lu = NULL;
+ state = sw_start;
+
+ for (p = name; *p; p++) {
+ ch = *p;
+
+ switch (state) {
+
+ case sw_start:
+
+ /*
+ * skip till first "/" to allow paths starting with drive and
+ * relative path, like "c:html/"
+ */
+
+ if (ch == '/' || ch == '\\') {
+ state = sw_after_slash;
+ }
+
+ break;
+
+ case sw_normal:
+
+ if (ch == ':') {
+ state = sw_after_colon;
+ break;
+ }
+
+ if (ch == '.' || ch == ' ') {
+ state = sw_after_dot;
+ break;
+ }
+
+ if (ch == '/' || ch == '\\') {
+ state = sw_after_slash;
+ break;
+ }
+
+ break;
+
+ case sw_after_slash:
+
+ if (ch == '/' || ch == '\\') {
+ break;
+ }
+
+ if (ch == '.') {
+ break;
+ }
+
+ if (ch == ':') {
+ state = sw_after_colon;
+ break;
+ }
+
+ state = sw_normal;
+ break;
+
+ case sw_after_colon:
+
+ if (ch == '/' || ch == '\\') {
+ state = sw_after_slash;
+ break;
+ }
+
+ goto invalid;
+
+ case sw_after_dot:
+
+ if (ch == '/' || ch == '\\') {
+ goto invalid;
+ }
+
+ if (ch == ':') {
+ goto invalid;
+ }
+
+ if (ch == '.' || ch == ' ') {
+ break;
+ }
+
+ state = sw_normal;
+ break;
+ }
+ }
+
+ if (state == sw_after_dot) {
+ goto invalid;
+ }
+
+ /* check if long name match */
+
+ lu = malloc(len * 2);
+ if (lu == NULL) {
+ return NGX_ERROR;
+ }
+
+ n = GetLongPathNameW(u, lu, len);
+
+ if (n == 0) {
+ goto failed;
+ }
+
+ if (n != len - 1 || _wcsicmp(u, lu) != 0) {
+ goto invalid;
+ }
+
+ return NGX_OK;
+
+invalid:
+
+ ngx_set_errno(NGX_ENOENT);
+
+failed:
+
+ if (lu) {
+ err = ngx_errno;
+ ngx_free(lu);
+ ngx_set_errno(err);
+ }
+
+ return NGX_ERROR;
+}
+
+
static u_short *
ngx_utf8_to_utf16(u_short *utf16, u_char *utf8, size_t *len)
{

_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel
Subject Author Views Posted

[nginx] svn commit: r4674 - trunk/src/os/win32

Anonymous User 969 June 05, 2012 09:38AM



Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 261
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready