|
Packit |
1fb8d4 |
/**
|
|
Packit |
1fb8d4 |
* FreeRDP: A Remote Desktop Protocol Implementation
|
|
Packit |
1fb8d4 |
* Certificate Handling
|
|
Packit |
1fb8d4 |
*
|
|
Packit |
1fb8d4 |
* Copyright 2011 Jiten Pathy
|
|
Packit |
1fb8d4 |
* Copyright 2011-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
|
Packit |
1fb8d4 |
*
|
|
Packit |
1fb8d4 |
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
Packit |
1fb8d4 |
* you may not use this file except in compliance with the License.
|
|
Packit |
1fb8d4 |
* You may obtain a copy of the License at
|
|
Packit |
1fb8d4 |
*
|
|
Packit |
1fb8d4 |
* http://www.apache.org/licenses/LICENSE-2.0
|
|
Packit |
1fb8d4 |
*
|
|
Packit |
1fb8d4 |
* Unless required by applicable law or agreed to in writing, software
|
|
Packit |
1fb8d4 |
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
Packit |
1fb8d4 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
Packit |
1fb8d4 |
* See the License for the specific language governing permissions and
|
|
Packit |
1fb8d4 |
* limitations under the License.
|
|
Packit |
1fb8d4 |
*/
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
1fb8d4 |
#include "config.h"
|
|
Packit |
1fb8d4 |
#endif
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#include <errno.h>
|
|
Packit |
1fb8d4 |
#include <stdio.h>
|
|
Packit |
1fb8d4 |
#include <string.h>
|
|
Packit |
1fb8d4 |
#include <ctype.h>
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#include <winpr/crypto.h>
|
|
Packit |
1fb8d4 |
#include <winpr/crt.h>
|
|
Packit |
1fb8d4 |
#include <winpr/file.h>
|
|
Packit |
1fb8d4 |
#include <winpr/path.h>
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#include <openssl/pem.h>
|
|
Packit |
1fb8d4 |
#include <openssl/rsa.h>
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static const char certificate_store_dir[] = "certs";
|
|
Packit |
1fb8d4 |
static const char certificate_server_dir[] = "server";
|
|
Packit |
1fb8d4 |
static const char certificate_known_hosts_file[] = "known_hosts2";
|
|
Packit |
1fb8d4 |
static const char certificate_legacy_hosts_file[] = "known_hosts";
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#include <freerdp/log.h>
|
|
Packit |
1fb8d4 |
#include <freerdp/crypto/certificate.h>
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#define TAG FREERDP_TAG("crypto")
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
static BOOL certificate_split_line(char* line, char** host, UINT16* port, char** subject,
|
|
Packit Service |
5a9772 |
char** issuer, char** fingerprint);
|
|
Packit |
1fb8d4 |
static BOOL certificate_line_is_comment(const char* line, size_t length)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
while (length > 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
switch (*line)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
case ' ':
|
|
Packit Service |
5a9772 |
case '\t':
|
|
Packit Service |
5a9772 |
line++;
|
|
Packit Service |
5a9772 |
length--;
|
|
Packit Service |
5a9772 |
break;
|
|
Packit Service |
5a9772 |
|
|
Packit Service |
5a9772 |
case '#':
|
|
Packit Service |
5a9772 |
return TRUE;
|
|
Packit Service |
5a9772 |
|
|
Packit Service |
5a9772 |
default:
|
|
Packit Service |
5a9772 |
return FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
return TRUE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
static BOOL certificate_store_init(rdpCertificateStore* certificate_store)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
char* server_path = NULL;
|
|
Packit |
1fb8d4 |
rdpSettings* settings;
|
|
Packit |
1fb8d4 |
settings = certificate_store->settings;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!PathFileExistsA(settings->ConfigPath))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (!PathMakePathA(settings->ConfigPath, 0))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_ERR(TAG, "error creating directory '%s'", settings->ConfigPath);
|
|
Packit |
1fb8d4 |
goto fail;
|
|
Packit |
1fb8d4 |
}
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
WLog_INFO(TAG, "creating directory %s", settings->ConfigPath);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
if (!(certificate_store->path =
|
|
Packit Service |
5a9772 |
GetCombinedPath(settings->ConfigPath, (char*)certificate_store_dir)))
|
|
Packit |
1fb8d4 |
goto fail;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!PathFileExistsA(certificate_store->path))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (!PathMakePathA(certificate_store->path, 0))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_ERR(TAG, "error creating directory [%s]", certificate_store->path);
|
|
Packit |
1fb8d4 |
goto fail;
|
|
Packit |
1fb8d4 |
}
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
WLog_INFO(TAG, "creating directory [%s]", certificate_store->path);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
if (!(server_path = GetCombinedPath(settings->ConfigPath, (char*)certificate_server_dir)))
|
|
Packit |
1fb8d4 |
goto fail;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!PathFileExistsA(server_path))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (!PathMakePathA(server_path, 0))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_ERR(TAG, "error creating directory [%s]", server_path);
|
|
Packit |
1fb8d4 |
goto fail;
|
|
Packit |
1fb8d4 |
}
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
WLog_INFO(TAG, "created directory [%s]", server_path);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
if (!(certificate_store->file =
|
|
Packit Service |
5a9772 |
GetCombinedPath(settings->ConfigPath, (char*)certificate_known_hosts_file)))
|
|
Packit |
1fb8d4 |
goto fail;
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
if (!(certificate_store->legacy_file =
|
|
Packit Service |
5a9772 |
GetCombinedPath(settings->ConfigPath, (char*)certificate_legacy_hosts_file)))
|
|
Packit |
1fb8d4 |
goto fail;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
free(server_path);
|
|
Packit |
1fb8d4 |
return TRUE;
|
|
Packit |
1fb8d4 |
fail:
|
|
Packit |
1fb8d4 |
WLog_ERR(TAG, "certificate store initialization failed");
|
|
Packit |
1fb8d4 |
free(server_path);
|
|
Packit |
1fb8d4 |
free(certificate_store->path);
|
|
Packit |
1fb8d4 |
free(certificate_store->file);
|
|
Packit |
1fb8d4 |
certificate_store->path = NULL;
|
|
Packit |
1fb8d4 |
certificate_store->file = NULL;
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static int certificate_data_match_legacy(rdpCertificateStore* certificate_store,
|
|
Packit Service |
5a9772 |
rdpCertificateData* certificate_data)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
HANDLE fp;
|
|
Packit |
1fb8d4 |
int match = 1;
|
|
Packit |
1fb8d4 |
char* data;
|
|
Packit |
1fb8d4 |
char* mdata;
|
|
Packit |
1fb8d4 |
char* pline;
|
|
Packit |
1fb8d4 |
char* hostname = NULL;
|
|
Packit |
1fb8d4 |
DWORD lowSize, highSize;
|
|
Packit |
1fb8d4 |
UINT64 size;
|
|
Packit |
1fb8d4 |
size_t length;
|
|
Packit |
1fb8d4 |
DWORD read;
|
|
Packit |
1fb8d4 |
/* Assure POSIX style paths, CreateFile expects either '/' or '\\' */
|
|
Packit Service |
5a9772 |
PathCchConvertStyleA(certificate_store->legacy_file, strlen(certificate_store->legacy_file),
|
|
Packit Service |
5a9772 |
PATH_STYLE_UNIX);
|
|
Packit Service |
5a9772 |
fp = CreateFileA(certificate_store->legacy_file, GENERIC_READ, FILE_SHARE_READ, NULL,
|
|
Packit Service |
5a9772 |
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (fp == INVALID_HANDLE_VALUE)
|
|
Packit |
1fb8d4 |
return match;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if ((lowSize = GetFileSize(fp, &highSize)) == INVALID_FILE_SIZE)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
WLog_ERR(TAG, "GetFileSize(%s) returned %s [0x%08" PRIX32 "]",
|
|
Packit Service |
5a9772 |
certificate_store->legacy_file, strerror(errno), GetLastError());
|
|
Packit |
1fb8d4 |
CloseHandle(fp);
|
|
Packit |
1fb8d4 |
return match;
|
|
Packit |
1fb8d4 |
}
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
size = (UINT64)lowSize | ((UINT64)highSize << 32);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (size < 1)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
CloseHandle(fp);
|
|
Packit |
1fb8d4 |
return match;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
mdata = (char*)malloc(size + 2);
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
if (!mdata)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
CloseHandle(fp);
|
|
Packit |
1fb8d4 |
return match;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
data = mdata;
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
if (!ReadFile(fp, data, size, &read, NULL) || (read != size))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
free(data);
|
|
Packit |
1fb8d4 |
CloseHandle(fp);
|
|
Packit |
1fb8d4 |
return match;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
CloseHandle(fp);
|
|
Packit |
1fb8d4 |
data[size] = '\n';
|
|
Packit |
1fb8d4 |
data[size + 1] = '\0';
|
|
Packit |
1fb8d4 |
pline = StrSep(&data, "\r\n");
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
while (pline != NULL)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
length = strlen(pline);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (length > 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
hostname = StrSep(&pline, " \t");
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
if (!hostname || !pline)
|
|
Packit Service |
5a9772 |
WLog_WARN(TAG, "Invalid %s entry %s %s!", certificate_legacy_hosts_file, hostname,
|
|
Packit Service |
5a9772 |
pline);
|
|
Packit |
1fb8d4 |
else if (strcmp(hostname, certificate_data->hostname) == 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
const int diff = strcmp(pline, certificate_data->fingerprint);
|
|
Packit |
1fb8d4 |
match = (diff == 0) ? 0 : -1;
|
|
Packit |
1fb8d4 |
break;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
pline = StrSep(&data, "\r\n");
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
/* Found a valid fingerprint in legacy file,
|
|
Packit |
1fb8d4 |
* copy to new file in new format. */
|
|
Packit |
1fb8d4 |
if (0 == match)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
rdpCertificateData* data = certificate_data_new(hostname, certificate_data->port, NULL,
|
|
Packit Service |
5a9772 |
NULL, certificate_data->fingerprint);
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
if (data)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
free(data->subject);
|
|
Packit Service |
5a9772 |
free(data->issuer);
|
|
Packit |
1fb8d4 |
data->subject = NULL;
|
|
Packit |
1fb8d4 |
data->issuer = NULL;
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
if (certificate_data->subject)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
data->subject = _strdup(certificate_data->subject);
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
if (!data->subject)
|
|
Packit |
1fb8d4 |
goto out;
|
|
Packit |
1fb8d4 |
}
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
if (certificate_data->issuer)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
data->issuer = _strdup(certificate_data->issuer);
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
if (!data->issuer)
|
|
Packit |
1fb8d4 |
goto out;
|
|
Packit |
1fb8d4 |
}
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
match = certificate_data_print(certificate_store, data) ? 0 : 1;
|
|
Packit |
1fb8d4 |
}
|
|
Packit Service |
5a9772 |
|
|
Packit Service |
5a9772 |
out:
|
|
Packit |
1fb8d4 |
certificate_data_free(data);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
free(mdata);
|
|
Packit |
1fb8d4 |
return match;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static int certificate_data_match_raw(rdpCertificateStore* certificate_store,
|
|
Packit Service |
5a9772 |
rdpCertificateData* certificate_data, char** psubject,
|
|
Packit Service |
5a9772 |
char** pissuer, char** fprint)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
BOOL found = FALSE;
|
|
Packit |
1fb8d4 |
HANDLE fp;
|
|
Packit |
1fb8d4 |
size_t length;
|
|
Packit |
1fb8d4 |
char* data;
|
|
Packit |
1fb8d4 |
char* mdata;
|
|
Packit |
1fb8d4 |
char* pline;
|
|
Packit |
1fb8d4 |
int match = 1;
|
|
Packit |
1fb8d4 |
DWORD lowSize, highSize;
|
|
Packit |
1fb8d4 |
UINT64 size;
|
|
Packit |
1fb8d4 |
char* hostname = NULL;
|
|
Packit |
1fb8d4 |
char* subject = NULL;
|
|
Packit |
1fb8d4 |
char* issuer = NULL;
|
|
Packit |
1fb8d4 |
char* fingerprint = NULL;
|
|
Packit |
1fb8d4 |
unsigned short port = 0;
|
|
Packit |
1fb8d4 |
DWORD read;
|
|
Packit |
1fb8d4 |
/* Assure POSIX style paths, CreateFile expects either '/' or '\\' */
|
|
Packit |
1fb8d4 |
PathCchConvertStyleA(certificate_store->file, strlen(certificate_store->file), PATH_STYLE_UNIX);
|
|
Packit Service |
5a9772 |
fp = CreateFileA(certificate_store->file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS,
|
|
Packit Service |
5a9772 |
FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL, NULL);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (fp == INVALID_HANDLE_VALUE)
|
|
Packit |
1fb8d4 |
return match;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if ((lowSize = GetFileSize(fp, &highSize)) == INVALID_FILE_SIZE)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
WLog_ERR(TAG, "GetFileSize(%s) returned %s [0x%08" PRIX32 "]",
|
|
Packit Service |
5a9772 |
certificate_store->legacy_file, strerror(errno), GetLastError());
|
|
Packit |
1fb8d4 |
CloseHandle(fp);
|
|
Packit |
1fb8d4 |
return match;
|
|
Packit |
1fb8d4 |
}
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
size = (UINT64)lowSize | ((UINT64)highSize << 32);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (size < 1)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
CloseHandle(fp);
|
|
Packit |
1fb8d4 |
return match;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
mdata = (char*)malloc(size + 2);
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
if (!mdata)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
CloseHandle(fp);
|
|
Packit |
1fb8d4 |
return match;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
data = mdata;
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
if (!ReadFile(fp, data, size, &read, NULL) || (read != size))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
free(data);
|
|
Packit |
1fb8d4 |
CloseHandle(fp);
|
|
Packit |
1fb8d4 |
return match;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
CloseHandle(fp);
|
|
Packit |
1fb8d4 |
data[size] = '\n';
|
|
Packit |
1fb8d4 |
data[size + 1] = '\0';
|
|
Packit |
1fb8d4 |
pline = StrSep(&data, "\r\n");
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
while (pline != NULL)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
length = strlen(pline);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (length > 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (certificate_line_is_comment(pline, length))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
}
|
|
Packit Service |
5a9772 |
else if (!certificate_split_line(pline, &hostname, &port, &subject, &issuer,
|
|
Packit Service |
5a9772 |
&fingerprint))
|
|
Packit Service |
5a9772 |
WLog_WARN(TAG, "Invalid %s entry %s!", certificate_known_hosts_file, pline);
|
|
Packit |
1fb8d4 |
else if (strcmp(pline, certificate_data->hostname) == 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
int outLen;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (port == certificate_data->port)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
found = TRUE;
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
if (fingerprint)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
match = (strcmp(certificate_data->fingerprint, fingerprint) == 0) ? 0 : -1;
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
if (fprint)
|
|
Packit |
1fb8d4 |
*fprint = _strdup(fingerprint);
|
|
Packit |
1fb8d4 |
}
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
if (subject && psubject)
|
|
Packit |
1fb8d4 |
crypto_base64_decode(subject, strlen(subject), (BYTE**)psubject, &outLen);
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
if (issuer && pissuer)
|
|
Packit |
1fb8d4 |
crypto_base64_decode(issuer, strlen(issuer), (BYTE**)pissuer, &outLen);
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
break;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
pline = StrSep(&data, "\r\n");
|
|
Packit |
1fb8d4 |
}
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
free(mdata);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if ((match != 0) && !found)
|
|
Packit |
1fb8d4 |
match = certificate_data_match_legacy(certificate_store, certificate_data);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
return match;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
BOOL certificate_get_stored_data(rdpCertificateStore* certificate_store,
|
|
Packit Service |
5a9772 |
rdpCertificateData* certificate_data, char** subject,
|
|
Packit Service |
5a9772 |
char** issuer, char** fingerprint)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
int rc = certificate_data_match_raw(certificate_store, certificate_data, subject, issuer,
|
|
Packit Service |
5a9772 |
fingerprint);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if ((rc == 0) || (rc == -1))
|
|
Packit |
1fb8d4 |
return TRUE;
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
int certificate_data_match(rdpCertificateStore* certificate_store,
|
|
Packit Service |
5a9772 |
rdpCertificateData* certificate_data)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
return certificate_data_match_raw(certificate_store, certificate_data, NULL, NULL, NULL);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
BOOL certificate_data_replace(rdpCertificateStore* certificate_store,
|
|
Packit Service |
5a9772 |
rdpCertificateData* certificate_data)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
HANDLE fp;
|
|
Packit |
1fb8d4 |
BOOL rc = FALSE;
|
|
Packit |
1fb8d4 |
size_t length;
|
|
Packit |
1fb8d4 |
char* data;
|
|
Packit |
1fb8d4 |
char* sdata;
|
|
Packit |
1fb8d4 |
char* pline;
|
|
Packit |
1fb8d4 |
UINT64 size;
|
|
Packit |
1fb8d4 |
DWORD read, written;
|
|
Packit |
1fb8d4 |
DWORD lowSize, highSize;
|
|
Packit |
1fb8d4 |
/* Assure POSIX style paths, CreateFile expects either '/' or '\\' */
|
|
Packit |
1fb8d4 |
PathCchConvertStyleA(certificate_store->file, strlen(certificate_store->file), PATH_STYLE_UNIX);
|
|
Packit Service |
5a9772 |
fp = CreateFileA(certificate_store->file, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
|
|
Packit Service |
5a9772 |
FILE_ATTRIBUTE_NORMAL, NULL);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (fp == INVALID_HANDLE_VALUE)
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if ((lowSize = GetFileSize(fp, &highSize)) == INVALID_FILE_SIZE)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
WLog_ERR(TAG, "GetFileSize(%s) returned %s [0x%08" PRIX32 "]",
|
|
Packit Service |
5a9772 |
certificate_store->legacy_file, strerror(errno), GetLastError());
|
|
Packit |
1fb8d4 |
CloseHandle(fp);
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
size = (UINT64)lowSize | ((UINT64)highSize << 32);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (size < 1)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
CloseHandle(fp);
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
data = (char*)malloc(size + 2);
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
if (!data)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
CloseHandle(fp);
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!ReadFile(fp, data, size, &read, NULL) || (read != size))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
free(data);
|
|
Packit |
1fb8d4 |
CloseHandle(fp);
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (SetFilePointer(fp, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
WLog_ERR(TAG, "SetFilePointer(%s) returned %s [0x%08" PRIX32 "]", certificate_store->file,
|
|
Packit Service |
5a9772 |
strerror(errno), GetLastError());
|
|
Packit |
1fb8d4 |
free(data);
|
|
Packit |
1fb8d4 |
CloseHandle(fp);
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!SetEndOfFile(fp))
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
WLog_ERR(TAG, "SetEndOfFile(%s) returned %s [0x%08" PRIX32 "]", certificate_store->file,
|
|
Packit Service |
5a9772 |
strerror(errno), GetLastError());
|
|
Packit |
1fb8d4 |
free(data);
|
|
Packit |
1fb8d4 |
CloseHandle(fp);
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
/* Write the file back out, with appropriate fingerprint substitutions */
|
|
Packit |
1fb8d4 |
data[size] = '\n';
|
|
Packit |
1fb8d4 |
data[size + 1] = '\0';
|
|
Packit |
1fb8d4 |
sdata = data;
|
|
Packit |
1fb8d4 |
pline = StrSep(&sdata, "\r\n");
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
while (pline != NULL)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
length = strlen(pline);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (length > 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
UINT16 port = 0;
|
|
Packit |
1fb8d4 |
char* hostname = NULL;
|
|
Packit |
1fb8d4 |
char* fingerprint = NULL;
|
|
Packit |
1fb8d4 |
char* subject = NULL;
|
|
Packit |
1fb8d4 |
char* issuer = NULL;
|
|
Packit |
1fb8d4 |
char* tdata;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (certificate_line_is_comment(pline, length))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
}
|
|
Packit Service |
5a9772 |
else if (!certificate_split_line(pline, &hostname, &port, &subject, &issuer,
|
|
Packit Service |
5a9772 |
&fingerprint))
|
|
Packit Service |
5a9772 |
WLog_WARN(TAG, "Skipping invalid %s entry %s!", certificate_known_hosts_file,
|
|
Packit Service |
5a9772 |
pline);
|
|
Packit |
1fb8d4 |
else
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
int res;
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
/* If this is the replaced hostname, use the updated fingerprint. */
|
|
Packit |
1fb8d4 |
if ((strcmp(hostname, certificate_data->hostname) == 0) &&
|
|
Packit Service |
5a9772 |
(port == certificate_data->port))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
fingerprint = certificate_data->fingerprint;
|
|
Packit |
1fb8d4 |
rc = TRUE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
res = _snprintf(NULL, 0, "%s %" PRIu16 " %s %s %s\n", hostname, port, fingerprint,
|
|
Packit Service |
5a9772 |
subject, issuer);
|
|
Packit Service |
5a9772 |
if (res < 0)
|
|
Packit Service |
5a9772 |
{
|
|
Packit Service |
5a9772 |
free(data);
|
|
Packit Service |
5a9772 |
CloseHandle(fp);
|
|
Packit Service |
5a9772 |
return FALSE;
|
|
Packit Service |
5a9772 |
}
|
|
Packit Service |
5a9772 |
size = (size_t)res;
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
tdata = malloc(size + 1);
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
if (!tdata)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
WLog_ERR(TAG, "malloc(%s) returned %s [0x%08X]", certificate_store->file,
|
|
Packit Service |
5a9772 |
strerror(errno), errno);
|
|
Packit Service |
5a9772 |
free(data);
|
|
Packit Service |
5a9772 |
CloseHandle(fp);
|
|
Packit Service |
5a9772 |
return FALSE;
|
|
Packit Service |
5a9772 |
}
|
|
Packit Service |
5a9772 |
|
|
Packit Service |
5a9772 |
res = _snprintf(tdata, size + 1, "%s %" PRIu16 " %s %s %s\n", hostname, port,
|
|
Packit Service |
5a9772 |
fingerprint, subject, issuer);
|
|
Packit Service |
5a9772 |
if (res < 0)
|
|
Packit Service |
5a9772 |
{
|
|
Packit Service |
5a9772 |
free(tdata);
|
|
Packit |
1fb8d4 |
free(data);
|
|
Packit |
1fb8d4 |
CloseHandle(fp);
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
if ((size_t)res != size)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
WLog_ERR(TAG, "_snprintf(%s) returned %s [0x%08X]", certificate_store->file,
|
|
Packit Service |
5a9772 |
strerror(errno), errno);
|
|
Packit |
1fb8d4 |
free(tdata);
|
|
Packit |
1fb8d4 |
free(data);
|
|
Packit |
1fb8d4 |
CloseHandle(fp);
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
if (!WriteFile(fp, tdata, size, &written, NULL) || (written != size))
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
WLog_ERR(TAG, "WriteFile(%s) returned %s [0x%08X]", certificate_store->file,
|
|
Packit Service |
5a9772 |
strerror(errno), errno);
|
|
Packit |
1fb8d4 |
free(tdata);
|
|
Packit |
1fb8d4 |
free(data);
|
|
Packit |
1fb8d4 |
CloseHandle(fp);
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
free(tdata);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
pline = StrSep(&sdata, "\r\n");
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
CloseHandle(fp);
|
|
Packit |
1fb8d4 |
free(data);
|
|
Packit |
1fb8d4 |
return rc;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
BOOL certificate_split_line(char* line, char** host, UINT16* port, char** subject, char** issuer,
|
|
Packit Service |
5a9772 |
char** fingerprint)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
char* cur;
|
|
Packit Service |
5a9772 |
size_t length = strlen(line);
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
if (length <= 0)
|
|
Packit Service |
5a9772 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
cur = StrSep(&line, " \t");
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
if (!cur)
|
|
Packit Service |
5a9772 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
*host = cur;
|
|
Packit Service |
5a9772 |
cur = StrSep(&line, " \t");
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
if (!cur)
|
|
Packit Service |
5a9772 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
if (sscanf(cur, "%hu", port) != 1)
|
|
Packit Service |
5a9772 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
cur = StrSep(&line, " \t");
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
if (!cur)
|
|
Packit Service |
5a9772 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
*fingerprint = cur;
|
|
Packit Service |
5a9772 |
cur = StrSep(&line, " \t");
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
if (!cur)
|
|
Packit Service |
5a9772 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
*subject = cur;
|
|
Packit Service |
5a9772 |
cur = StrSep(&line, " \t");
|
|
Packit Service |
5a9772 |
|
|
Packit Service |
5a9772 |
if (!cur)
|
|
Packit Service |
5a9772 |
return FALSE;
|
|
Packit Service |
5a9772 |
|
|
Packit Service |
5a9772 |
*issuer = cur;
|
|
Packit Service |
5a9772 |
return TRUE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
BOOL certificate_data_print(rdpCertificateStore* certificate_store,
|
|
Packit Service |
5a9772 |
rdpCertificateData* certificate_data)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
int rc;
|
|
Packit |
1fb8d4 |
HANDLE fp;
|
|
Packit |
1fb8d4 |
char* tdata;
|
|
Packit Service |
5a9772 |
size_t size;
|
|
Packit |
1fb8d4 |
DWORD written;
|
|
Packit |
1fb8d4 |
/* reopen in append mode */
|
|
Packit |
1fb8d4 |
/* Assure POSIX style paths, CreateFile expects either '/' or '\\' */
|
|
Packit |
1fb8d4 |
PathCchConvertStyleA(certificate_store->file, strlen(certificate_store->file), PATH_STYLE_UNIX);
|
|
Packit Service |
5a9772 |
fp = CreateFileA(certificate_store->file, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
|
|
Packit Service |
5a9772 |
FILE_ATTRIBUTE_NORMAL, NULL);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (fp == INVALID_HANDLE_VALUE)
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (SetFilePointer(fp, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
WLog_ERR(TAG, "SetFilePointer(%s) returned %s [0x%08" PRIX32 "]", certificate_store->file,
|
|
Packit Service |
5a9772 |
strerror(errno), GetLastError());
|
|
Packit |
1fb8d4 |
CloseHandle(fp);
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
rc = _snprintf(NULL, 0, "%s %" PRIu16 " %s %s %s\n", certificate_data->hostname,
|
|
Packit Service |
5a9772 |
certificate_data->port, certificate_data->fingerprint, certificate_data->subject,
|
|
Packit Service |
5a9772 |
certificate_data->issuer);
|
|
Packit Service |
5a9772 |
if (rc < 0)
|
|
Packit Service |
5a9772 |
return FALSE;
|
|
Packit Service |
5a9772 |
size = (size_t)rc;
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
tdata = malloc(size + 1);
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
if (!tdata)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
WLog_ERR(TAG, "malloc(%s) returned %s [0x%08X]", certificate_store->file, strerror(errno),
|
|
Packit Service |
5a9772 |
errno);
|
|
Packit |
1fb8d4 |
CloseHandle(fp);
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit Service |
5a9772 |
|
|
Packit Service |
5a9772 |
rc = _snprintf(tdata, size + 1, "%s %" PRIu16 " %s %s %s\n", certificate_data->hostname,
|
|
Packit Service |
5a9772 |
certificate_data->port, certificate_data->fingerprint, certificate_data->subject,
|
|
Packit Service |
5a9772 |
certificate_data->issuer);
|
|
Packit Service |
5a9772 |
|
|
Packit Service |
5a9772 |
if ((rc < 0) || ((size_t)rc != size))
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
WLog_ERR(TAG, "_snprintf(%s) returned %s [0x%08X]", certificate_store->file,
|
|
Packit Service |
5a9772 |
strerror(errno), errno);
|
|
Packit |
1fb8d4 |
free(tdata);
|
|
Packit |
1fb8d4 |
CloseHandle(fp);
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
if (!WriteFile(fp, tdata, size, &written, NULL) || (written != size))
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
WLog_ERR(TAG, "WriteFile(%s) returned %s [0x%08X]", certificate_store->file,
|
|
Packit Service |
5a9772 |
strerror(errno), errno);
|
|
Packit |
1fb8d4 |
free(tdata);
|
|
Packit |
1fb8d4 |
CloseHandle(fp);
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
free(tdata);
|
|
Packit |
1fb8d4 |
CloseHandle(fp);
|
|
Packit |
1fb8d4 |
return TRUE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
rdpCertificateData* certificate_data_new(const char* hostname, UINT16 port, const char* subject,
|
|
Packit Service |
5a9772 |
const char* issuer, const char* fingerprint)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
size_t i;
|
|
Packit |
1fb8d4 |
rdpCertificateData* certdata;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!hostname)
|
|
Packit |
1fb8d4 |
return NULL;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!fingerprint)
|
|
Packit |
1fb8d4 |
return NULL;
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
certdata = (rdpCertificateData*)calloc(1, sizeof(rdpCertificateData));
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
if (!certdata)
|
|
Packit |
1fb8d4 |
return NULL;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
certdata->port = port;
|
|
Packit |
1fb8d4 |
certdata->hostname = _strdup(hostname);
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
if (subject)
|
|
Packit Service |
5a9772 |
certdata->subject = crypto_base64_encode((const BYTE*)subject, strlen(subject));
|
|
Packit |
1fb8d4 |
else
|
|
Packit Service |
5a9772 |
certdata->subject = crypto_base64_encode((const BYTE*)"", 0);
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
if (issuer)
|
|
Packit Service |
5a9772 |
certdata->issuer = crypto_base64_encode((const BYTE*)issuer, strlen(issuer));
|
|
Packit |
1fb8d4 |
else
|
|
Packit Service |
5a9772 |
certdata->issuer = crypto_base64_encode((const BYTE*)"", 0);
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
certdata->fingerprint = _strdup(fingerprint);
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
if (!certdata->hostname || !certdata->subject || !certdata->issuer || !certdata->fingerprint)
|
|
Packit |
1fb8d4 |
goto fail;
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
for (i = 0; i < strlen(hostname); i++)
|
|
Packit |
1fb8d4 |
certdata->hostname[i] = tolower(certdata->hostname[i]);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
return certdata;
|
|
Packit |
1fb8d4 |
fail:
|
|
Packit |
1fb8d4 |
free(certdata->hostname);
|
|
Packit |
1fb8d4 |
free(certdata->subject);
|
|
Packit |
1fb8d4 |
free(certdata->issuer);
|
|
Packit |
1fb8d4 |
free(certdata->fingerprint);
|
|
Packit |
1fb8d4 |
free(certdata);
|
|
Packit |
1fb8d4 |
return NULL;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
void certificate_data_free(rdpCertificateData* certificate_data)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (certificate_data != NULL)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
free(certificate_data->hostname);
|
|
Packit |
1fb8d4 |
free(certificate_data->subject);
|
|
Packit |
1fb8d4 |
free(certificate_data->issuer);
|
|
Packit |
1fb8d4 |
free(certificate_data->fingerprint);
|
|
Packit |
1fb8d4 |
free(certificate_data);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
rdpCertificateStore* certificate_store_new(rdpSettings* settings)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
rdpCertificateStore* certificate_store;
|
|
Packit Service |
5a9772 |
certificate_store = (rdpCertificateStore*)calloc(1, sizeof(rdpCertificateStore));
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!certificate_store)
|
|
Packit |
1fb8d4 |
return NULL;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
certificate_store->settings = settings;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!certificate_store_init(certificate_store))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
free(certificate_store);
|
|
Packit |
1fb8d4 |
return NULL;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
return certificate_store;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
void certificate_store_free(rdpCertificateStore* certstore)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (certstore != NULL)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
free(certstore->path);
|
|
Packit |
1fb8d4 |
free(certstore->file);
|
|
Packit |
1fb8d4 |
free(certstore->legacy_file);
|
|
Packit |
1fb8d4 |
free(certstore);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|