Using locking winpr file functions for known hosts.
authorArmin Novak <armin.novak@thincast.com>
Wed, 9 Dec 2015 17:29:41 +0000 (18:29 +0100)
committerArmin Novak <armin.novak@thincast.com>
Wed, 9 Dec 2015 17:29:41 +0000 (18:29 +0100)
libfreerdp/crypto/certificate.c

index e8d2923..7665677 100644 (file)
@@ -116,63 +116,55 @@ fail:
 static int certificate_data_match_legacy(rdpCertificateStore* certificate_store,
                                         rdpCertificateData* certificate_data)
 {
-       FILE* fp;
+       HANDLE fp;
        int match = 1;
        char* data;
        char* mdata;
        char* pline;
        char* hostname;
-       long size;
+       DWORD lowSize, highSize;
+       UINT64 size;
        size_t length;
+       DWORD read;
 
-       fp = fopen(certificate_store->legacy_file, "rb");
-       if (!fp)
+       /* Assure POSIX style paths, CreateFile expects either '/' or '\\' */
+       PathCchConvertStyleA(certificate_store->legacy_file, strlen(certificate_store->legacy_file), PATH_STYLE_UNIX);
+       fp = CreateFileA(certificate_store->legacy_file, GENERIC_READ, FILE_SHARE_READ,
+                                       NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+       if (fp == INVALID_HANDLE_VALUE)
                return match;
 
-       if (fseek(fp, 0, SEEK_END) < 0)
+       if ((lowSize = GetFileSize(fp, &highSize)) == INVALID_FILE_SIZE)
        {
-               WLog_ERR(TAG, "fseek(%s) returned %s [%08X]",
-                        certificate_store->legacy_file, strerror(errno), errno);
-               fclose(fp);
-               return match;
-       }
-       if ((size = ftell(fp)) < 0)
-       {
-               WLog_ERR(TAG, "ftell(%s) returned %s [%08X]",
-                        certificate_store->legacy_file, strerror(errno), errno);
-               fclose(fp);
-               return match;
-       }
-       if (fseek(fp, 0, SEEK_SET) < 0)
-       {
-               WLog_ERR(TAG, "fseek(%s) returned %s [%08X]",
-                        certificate_store->legacy_file, strerror(errno), errno);
-               fclose(fp);
+               WLog_ERR(TAG, "GetFileSize(%s) returned %s [%08X]",
+                        certificate_store->legacy_file, strerror(errno), GetLastError());
+               CloseHandle(fp);
                return match;
        }
+       size = (UINT64)lowSize | ((UINT64)highSize << 32);
 
        if (size < 1)
        {
-               fclose(fp);
+               CloseHandle(fp);
                return match;
        }
 
        mdata = (char*) malloc(size + 2);
        if (!mdata)
        {
-               fclose(fp);
+               CloseHandle(fp);
                return match;
        }
 
        data = mdata;
-       if (fread(data, size, 1, fp) != 1)
+       if (!ReadFile(fp, data, size, &read, NULL) || (read != size))
        {
                free(data);
-               fclose(fp);
+               CloseHandle(fp);
                return match;
        }
 
-       fclose(fp);
+       CloseHandle(fp);
 
        data[size] = '\n';
        data[size + 1] = '\0';
@@ -243,67 +235,59 @@ static int certificate_data_match_raw(rdpCertificateStore* certificate_store,
                                                        char** fprint)
 {
        BOOL found = FALSE;
-       FILE* fp;
+       HANDLE fp;
        size_t length;
        char* data;
        char* mdata;
        char* pline;
        int match = 1;
-       long int size;
+       DWORD lowSize, highSize;
+       UINT64 size;
        char* hostname = NULL;
        char* subject = NULL;
        char* issuer = NULL;
        char* fingerprint = NULL;
        unsigned short port = 0;
+       DWORD read;
 
-       fp = fopen(certificate_store->file, "rb");
+       /* Assure POSIX style paths, CreateFile expects either '/' or '\\' */
+       PathCchConvertStyleA(certificate_store->file, strlen(certificate_store->file), PATH_STYLE_UNIX);
+       fp = CreateFileA(certificate_store->file, GENERIC_READ, FILE_SHARE_READ,
+                                       NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL, NULL);
 
-       if (!fp)
+       if (fp == INVALID_HANDLE_VALUE)
                return match;
 
-       if (fseek(fp, 0, SEEK_END) < 0)
-       {
-               WLog_ERR(TAG, "fseek(%s) returned %s [%08X]",
-                        certificate_store->file, strerror(errno), errno);
-               fclose(fp);
-               return match;
-       }
-       if ((size = ftell(fp)) < 0)
+       if ((lowSize = GetFileSize(fp, &highSize)) == INVALID_FILE_SIZE)
        {
-               WLog_ERR(TAG, "ftell(%s) returned %s [%08X]",
-                        certificate_store->file, strerror(errno), errno);
-               fclose(fp);
-               return match;
-       }
-       if (fseek(fp, 0, SEEK_SET) < 0)
-       {
-               WLog_ERR(TAG, "fseek(%s) returned %s [%08X]",
-                        certificate_store->file, strerror(errno), errno);
-               fclose(fp);
+               WLog_ERR(TAG, "GetFileSize(%s) returned %s [%08X]",
+                        certificate_store->legacy_file, strerror(errno), GetLastError());
+               CloseHandle(fp);
                return match;
        }
+       size = (UINT64)lowSize | ((UINT64)highSize << 32);
 
        if (size < 1)
        {
-               fclose(fp);
+               CloseHandle(fp);
                return match;
        }
 
        mdata = (char*) malloc(size + 2);
        if (!mdata)
        {
-               fclose(fp);
+               CloseHandle(fp);
                return match;
        }
 
        data = mdata;
-       if (fread(data, size, 1, fp) != 1)
+       if (!ReadFile(fp, data, size, &read, NULL) || (read != size))
        {
-               fclose(fp);
                free(data);
+               CloseHandle(fp);
                return match;
        }
-       fclose(fp);
+       CloseHandle(fp);
 
        data[size] = '\n';
        data[size + 1] = '\0';
@@ -371,40 +355,36 @@ int certificate_data_match(rdpCertificateStore* certificate_store,
 BOOL certificate_data_replace(rdpCertificateStore* certificate_store,
                                                rdpCertificateData* certificate_data)
 {
-       FILE* fp;
+       HANDLE fp;
        BOOL rc = FALSE;
        size_t length;
        char* data;
        char* sdata;
        char* pline;
-       long int size;
+       UINT64 size;
+       DWORD read, written;
+       DWORD lowSize, highSize;
 
-       fp = fopen(certificate_store->file, "rb");
+       /* Assure POSIX style paths, CreateFile expects either '/' or '\\' */
+       PathCchConvertStyleA(certificate_store->file, strlen(certificate_store->file), PATH_STYLE_UNIX);
+       fp = CreateFileA(certificate_store->file, GENERIC_READ | GENERIC_WRITE, 0,
+                                       NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
 
-       if (!fp)
-               return FALSE;
-       /* Read the current contents of the file. */
-       if (fseek(fp, 0, SEEK_END) < 0)
-       {
-               WLog_ERR(TAG, "fseek(%s) returned %s [%08X]",
-                        certificate_store->file, strerror(errno), errno);
-               fclose(fp);
+       if (fp == INVALID_HANDLE_VALUE)
                return FALSE;
-       }
 
-       if ((size = ftell(fp)) < 0)
+       if ((lowSize = GetFileSize(fp, &highSize)) == INVALID_FILE_SIZE)
        {
-               WLog_ERR(TAG, "ftell(%s) returned %s [%08X]",
-                        certificate_store->file, strerror(errno), errno);
-               fclose(fp);
+               WLog_ERR(TAG, "GetFileSize(%s) returned %s [%08X]",
+                        certificate_store->legacy_file, strerror(errno), GetLastError());
+               CloseHandle(fp);
                return FALSE;
        }
+       size = (UINT64)lowSize | ((UINT64)highSize << 32);
 
-       if (fseek(fp, 0, SEEK_SET) < 0)
+       if (size < 1)
        {
-               WLog_ERR(TAG, "fseek(%s) returned %s [%08X]",
-                        certificate_store->file, strerror(errno), errno);
-               fclose(fp);
+               CloseHandle(fp);
                return FALSE;
        }
 
@@ -415,22 +395,26 @@ BOOL certificate_data_replace(rdpCertificateStore* certificate_store,
                return FALSE;
        }
 
-       if (fread(data, size, 1, fp) != 1)
+       if (!ReadFile(fp, data, size, &read, NULL) || (read != size))
        {
-               fclose(fp);
                free(data);
+               CloseHandle(fp);
                return FALSE;
        }
 
-       fclose(fp);
-
-       fp = fopen(certificate_store->file, "wb");
+       if (SetFilePointer(fp, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
+       {
+               WLog_ERR(TAG, "SetFilePointer(%s) returned %s [%08X]",
+                        certificate_store->file, strerror(errno), GetLastError());
+               CloseHandle(fp);
+               return FALSE;
+       }
 
-       if (fp == NULL)
+       if (!SetEndOfFile(fp))
        {
-               WLog_ERR(TAG, "freopen(%s) returned %s [%08X]",
-                        certificate_store->file, strerror(errno), errno);
-               free(data);
+               WLog_ERR(TAG, "SetEndOfFile(%s) returned %s [%08X]",
+                        certificate_store->file, strerror(errno), GetLastError());
+               CloseHandle(fp);
                return FALSE;
        }
 
@@ -451,6 +435,7 @@ BOOL certificate_data_replace(rdpCertificateStore* certificate_store,
                        char* fingerprint = NULL;
                        char* subject = NULL;
                        char* issuer = NULL;
+                       char* tdata;
 
                        if (!certificate_split_line(pline, &hostname, &port, &subject, &issuer, &fingerprint))
                                WLog_WARN(TAG, "Skipping invalid %s entry %s!",
@@ -464,26 +449,41 @@ BOOL certificate_data_replace(rdpCertificateStore* certificate_store,
                                        fingerprint = certificate_data->fingerprint;
                                        rc = TRUE;
                                }
-                               if (fprintf(fp, "%s %hu %s %s %s\n", hostname, port, fingerprint, subject, issuer) < 0)
+
+                               size = _snprintf(NULL, 0, "%s %hu %s %s %s\n", hostname, port, fingerprint, subject, issuer);
+                               tdata = malloc(size + 1);
+                               if (!tdata)
+                               {
+                                       WLog_ERR(TAG, "malloc(%s) returned %s [%08X]",
+                                                certificate_store->file, strerror(errno), errno);
+                                       CloseHandle(fp);
+                                       return FALSE;
+                               }
+
+                               if (_snprintf(tdata, size + 1, "%s %hu %s %s %s\n", hostname, port, fingerprint, subject, issuer) != size)
                                {
-                                       WLog_ERR(TAG, "fprintf(%s) returned %s [%08X]",
+                                       WLog_ERR(TAG, "_snprintf(%s) returned %s [%08X]",
                                                 certificate_store->file, strerror(errno), errno);
-                                       fclose(fp);
+                                       free(tdata);
+                                       CloseHandle(fp);
                                        return FALSE;
                                }
+                               if (!WriteFile(fp, tdata, size, &written, NULL) || (written != size))
+                               {
+                                       WLog_ERR(TAG, "WriteFile(%s) returned %s [%08X]",
+                                                certificate_store->file, strerror(errno), errno);
+                                       free(tdata);
+                                       CloseHandle(fp);
+                                       return FALSE;
+                               }
+                               free(tdata);
                        }
                }
 
                pline = StrSep(&sdata, "\r\n");
        }
 
-       if (fflush(fp) != 0)
-       {
-               WLog_WARN(TAG, "fflush(%s) returned %s [%08X]",
-                        certificate_store->file, strerror(errno), errno);
-       }
-
-       fclose(fp);
+       CloseHandle(fp);
        free(data);
 
        return rc;
@@ -533,39 +533,60 @@ BOOL certificate_split_line(char* line, char** host, UINT16* port, char** subjec
 
 BOOL certificate_data_print(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data)
 {
-       FILE* fp;
+       HANDLE fp;
+       char* tdata;
+       UINT64 size;
+       DWORD written;
 
        /* reopen in append mode */
-       fp = fopen(certificate_store->file, "ab");
+       /* Assure POSIX style paths, CreateFile expects either '/' or '\\' */
+       PathCchConvertStyleA(certificate_store->file, strlen(certificate_store->file), PATH_STYLE_UNIX);
+       fp = CreateFileA(certificate_store->file, GENERIC_WRITE, 0,
+                                       NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
 
-       if (!fp)
+       if (fp == INVALID_HANDLE_VALUE)
                return FALSE;
 
-       if (fseek(fp, 0, SEEK_END) < 0)
+       if (SetFilePointer(fp, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER)
        {
-               WLog_ERR(TAG, "fseek(%s) returned %s [%08X]",
-                        certificate_store->file, strerror(errno), errno);
-               fclose(fp);
+               WLog_ERR(TAG, "SetFilePointer(%s) returned %s [%08X]",
+                        certificate_store->file, strerror(errno), GetLastError());
+               CloseHandle(fp);
                return FALSE;
        }
 
-       if (fprintf(fp, "%s %hu %s %s %s\n", certificate_data->hostname, certificate_data->port,
+       size = _snprintf(NULL, 0, "%s %hu %s %s %s\n", certificate_data->hostname, certificate_data->port,
                                         certificate_data->fingerprint, certificate_data->subject,
-                                        certificate_data->issuer) < 0)
+                                        certificate_data->issuer);
+       tdata = malloc(size + 1);
+       if (!tdata)
        {
-               WLog_ERR(TAG, "fprintf(%s) returned %s [%08X]",
+               WLog_ERR(TAG, "malloc(%s) returned %s [%08X]",
                         certificate_store->file, strerror(errno), errno);
-               fclose(fp);
+               CloseHandle(fp);
                return FALSE;
        }
-
-       if (fflush(fp) != 0)
+       if (_snprintf(tdata, size + 1, "%s %hu %s %s %s\n", certificate_data->hostname, certificate_data->port,
+                                 certificate_data->fingerprint, certificate_data->subject,
+                                 certificate_data->issuer) != size)
+       {
+               WLog_ERR(TAG, "_snprintf(%s) returned %s [%08X]",
+                        certificate_store->file, strerror(errno), errno);
+               free(tdata);
+               CloseHandle(fp);
+               return FALSE;
+       }
+       if (!WriteFile(fp, tdata, size, &written, NULL) || (written != size))
        {
-               WLog_WARN(TAG, "fflush(%s) returned %s [%08X]",
+               WLog_ERR(TAG, "WriteFile(%s) returned %s [%08X]",
                         certificate_store->file, strerror(errno), errno);
+               free(tdata);
+               CloseHandle(fp);
+               return FALSE;
        }
+       free(tdata);
 
-       fclose(fp);
+       CloseHandle(fp);
 
        return TRUE;
 }