fix lsa auth provider and minor bug fixes (#270)
https://github.com/PowerShell/Win32-OpenSSH/issues/1046
This commit is contained in:
parent
02d07309e2
commit
b10f2232e5
|
@ -231,7 +231,7 @@ sys_auth_passwd(Authctxt *authctxt, const char *password)
|
||||||
|
|
||||||
#elif defined(WINDOWS)
|
#elif defined(WINDOWS)
|
||||||
HANDLE password_auth_token = NULL;
|
HANDLE password_auth_token = NULL;
|
||||||
HANDLE process_custom_lsa_auth(char*, const char*, char*);
|
HANDLE process_custom_lsa_auth(const char*, const char*, const char*);
|
||||||
|
|
||||||
void
|
void
|
||||||
sys_auth_passwd_lsa(Authctxt *authctxt, const char *password)
|
sys_auth_passwd_lsa(Authctxt *authctxt, const char *password)
|
||||||
|
@ -253,8 +253,7 @@ sys_auth_passwd_lsa(Authctxt *authctxt, const char *password)
|
||||||
lsa_auth_pkg = utf16_to_utf8(lsa_auth_pkg_w);
|
lsa_auth_pkg = utf16_to_utf8(lsa_auth_pkg_w);
|
||||||
if (!lsa_auth_pkg)
|
if (!lsa_auth_pkg)
|
||||||
fatal("utf16_to_utf8 failed to convert lsa_auth_pkg_w:%ls", lsa_auth_pkg_w);
|
fatal("utf16_to_utf8 failed to convert lsa_auth_pkg_w:%ls", lsa_auth_pkg_w);
|
||||||
|
|
||||||
debug("Authenticating using LSA Auth Package:%ls", lsa_auth_pkg_w);
|
|
||||||
password_auth_token = process_custom_lsa_auth(authctxt->pw->pw_name, password, lsa_auth_pkg);
|
password_auth_token = process_custom_lsa_auth(authctxt->pw->pw_name, password, lsa_auth_pkg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
auth.c
2
auth.c
|
@ -430,7 +430,7 @@ expand_authorized_keys(const char *filename, struct passwd *pw)
|
||||||
|
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
/* Return if the path is absolute. If not, prepend the '%h\\' */
|
/* Return if the path is absolute. If not, prepend the '%h\\' */
|
||||||
if ((strlen(file) > 1) && (file[1] == ':'))
|
if(is_absolute_path(file))
|
||||||
return (file);
|
return (file);
|
||||||
|
|
||||||
i = snprintf(ret, sizeof(ret), "%s\\%s", pw->pw_dir, file);
|
i = snprintf(ret, sizeof(ret), "%s\\%s", pw->pw_dir, file);
|
||||||
|
|
|
@ -1460,7 +1460,7 @@ int
|
||||||
is_absolute_path(char *path)
|
is_absolute_path(char *path)
|
||||||
{
|
{
|
||||||
int retVal = 0;
|
int retVal = 0;
|
||||||
if (*path == '/' || *path == '\\' || (*path != '\0' && path[1] == ':') ||
|
if (*path == '/' || *path == '\\' || (*path != '\0' && isalpha(*path) && path[1] == ':') ||
|
||||||
((strlen(path) >= strlen(PROGRAM_DATA)) && (memcmp(path, PROGRAM_DATA, strlen(PROGRAM_DATA)) == 0)))
|
((strlen(path) >= strlen(PROGRAM_DATA)) && (memcmp(path, PROGRAM_DATA, strlen(PROGRAM_DATA)) == 0)))
|
||||||
retVal = 1;
|
retVal = 1;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#include <VersionHelpers.h>
|
#include <VersionHelpers.h>
|
||||||
|
|
||||||
#define PATH_MAX MAX_PATH
|
#define PATH_MAX MAX_PATH
|
||||||
|
#define SSH_REGISTRY_ROOT L"SOFTWARE\\OpenSSH"
|
||||||
#define GOTO_CLEANUP_IF(_cond_,_err_) do { \
|
#define GOTO_CLEANUP_IF(_cond_,_err_) do { \
|
||||||
if ((_cond_)) { \
|
if ((_cond_)) { \
|
||||||
hr = _err_; \
|
hr = _err_; \
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "Debug.h"
|
#include "Debug.h"
|
||||||
|
#include "misc_internal.h"
|
||||||
|
|
||||||
#define MAX_MESSAGE_SIZE 256 * 1024
|
#define MAX_MESSAGE_SIZE 256 * 1024
|
||||||
|
|
||||||
#define SSH_ROOT L"SOFTWARE\\OpenSSH"
|
#define SSH_AGENT_ROOT SSH_REGISTRY_ROOT L"\\Agent"
|
||||||
#define SSH_AGENT_ROOT SSH_ROOT L"\\Agent"
|
|
||||||
#define SSH_KEYS_KEY L"Keys"
|
#define SSH_KEYS_KEY L"Keys"
|
||||||
#define SSH_KEYS_ROOT SSH_AGENT_ROOT L"\\" SSH_KEYS_KEY
|
#define SSH_KEYS_ROOT SSH_AGENT_ROOT L"\\" SSH_KEYS_KEY
|
||||||
|
|
||||||
|
|
|
@ -1040,6 +1040,7 @@ spawn_child_internal(char* cmd, char *const argv[], HANDLE in, HANDLE out, HANDL
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
errno = GetLastError();
|
errno = GetLastError();
|
||||||
|
error("%s failed error:%d", (as_user?"CreateProcessAsUserW":"CreateProcessW"), GetLastError());
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,8 @@
|
||||||
#include <Ntsecapi.h>
|
#include <Ntsecapi.h>
|
||||||
#include <ntstatus.h>
|
#include <ntstatus.h>
|
||||||
#include <Shlobj.h>
|
#include <Shlobj.h>
|
||||||
|
#include <LM.h>
|
||||||
|
|
||||||
#include "inc\utf.h"
|
#include "inc\utf.h"
|
||||||
#include "logonuser.h"
|
#include "logonuser.h"
|
||||||
#include <Ntsecapi.h>
|
#include <Ntsecapi.h>
|
||||||
|
@ -223,14 +225,14 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLE
|
HANDLE
|
||||||
process_custom_lsa_auth(char* user, const char* pwd, char* lsa_pkg)
|
process_custom_lsa_auth(const char* user, const char* pwd, const char* lsa_pkg)
|
||||||
{
|
{
|
||||||
wchar_t *userw = NULL, *pwdw = NULL, *domw = NULL, *tmp, *providerw = NULL;
|
wchar_t *providerw = NULL;
|
||||||
HANDLE token = NULL, lsa_handle = NULL;
|
HANDLE token = NULL, lsa_handle = NULL;
|
||||||
LSA_OPERATIONAL_MODE mode;
|
LSA_OPERATIONAL_MODE mode;
|
||||||
ULONG auth_package_id, logon_info_size = 0;
|
ULONG auth_package_id, logon_info_size = 0;
|
||||||
NTSTATUS ret, subStatus;
|
NTSTATUS ret, subStatus;
|
||||||
wchar_t *logon_info = NULL;
|
wchar_t *logon_info_w = NULL;
|
||||||
LSA_STRING logon_process_name, lsa_auth_package_name, originName;
|
LSA_STRING logon_process_name, lsa_auth_package_name, originName;
|
||||||
TOKEN_SOURCE sourceContext;
|
TOKEN_SOURCE sourceContext;
|
||||||
PVOID pProfile = NULL;
|
PVOID pProfile = NULL;
|
||||||
|
@ -238,19 +240,34 @@ process_custom_lsa_auth(char* user, const char* pwd, char* lsa_pkg)
|
||||||
QUOTA_LIMITS quotas;
|
QUOTA_LIMITS quotas;
|
||||||
DWORD cbProfile;
|
DWORD cbProfile;
|
||||||
int retVal = -1;
|
int retVal = -1;
|
||||||
|
char *domain = NULL, *logon_info = NULL, user_name[UNLEN] = { 0, }, *tmp = NULL;
|
||||||
|
|
||||||
debug("LSA auth request, user:%s lsa_pkg:%s ", user, lsa_pkg);
|
debug3("LSA auth request, user:%s lsa_pkg:%s ", user, lsa_pkg);
|
||||||
|
|
||||||
if ((userw = utf8_to_utf16(user)) == NULL ||
|
logon_info_size = (ULONG)(strlen(user) + strlen(pwd) + 2); // 1 - ";", 1 - "\0"
|
||||||
(pwdw = utf8_to_utf16(pwd)) == NULL) {
|
strcpy_s(user_name, _countof(user_name), user);
|
||||||
debug("out of memory");
|
if (tmp = strstr(user_name, "@")) {
|
||||||
goto done;
|
domain = tmp + 1;
|
||||||
|
*tmp = '\0';
|
||||||
|
logon_info_size++; // 1 - ";"
|
||||||
}
|
}
|
||||||
|
|
||||||
/* split user and domain */
|
logon_info = malloc(logon_info_size);
|
||||||
if ((tmp = wcschr(userw, L'@')) != NULL) {
|
if(!logon_info)
|
||||||
domw = tmp + 1;
|
fatal("%s out of memory", __func__);
|
||||||
*tmp = L'\0';
|
|
||||||
|
strcpy_s(logon_info, logon_info_size, user_name);
|
||||||
|
strcat_s(logon_info, logon_info_size, ";");
|
||||||
|
strcat_s(logon_info, logon_info_size, pwd);
|
||||||
|
|
||||||
|
if (domain) {
|
||||||
|
strcat_s(logon_info, logon_info_size, ";");
|
||||||
|
strcat_s(logon_info, logon_info_size, domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NULL == (logon_info_w = utf8_to_utf16(logon_info))) {
|
||||||
|
error("utf8_to_utf16 failed to convert %s", logon_info);
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* call into LSA provider , get and duplicate token */
|
/* call into LSA provider , get and duplicate token */
|
||||||
|
@ -268,30 +285,19 @@ process_custom_lsa_auth(char* user, const char* pwd, char* lsa_pkg)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
logon_info_size = (ULONG)((wcslen(userw) + wcslen(pwdw) + wcslen(domw) + 3) * sizeof(wchar_t));
|
|
||||||
logon_info = (wchar_t *)malloc(logon_info_size);
|
|
||||||
if (NULL == logon_info)
|
|
||||||
fatal("%s:out of memory", __func__);
|
|
||||||
|
|
||||||
wcscpy_s(logon_info, logon_info_size, userw);
|
|
||||||
wcscat_s(logon_info, logon_info_size, L";");
|
|
||||||
wcscat_s(logon_info, logon_info_size, pwdw);
|
|
||||||
wcscat_s(logon_info, logon_info_size, L";");
|
|
||||||
wcscat_s(logon_info, logon_info_size, domw);
|
|
||||||
|
|
||||||
memcpy(sourceContext.SourceName, "sshd", sizeof(sourceContext.SourceName));
|
memcpy(sourceContext.SourceName, "sshd", sizeof(sourceContext.SourceName));
|
||||||
|
|
||||||
if (!AllocateLocallyUniqueId(&sourceContext.SourceIdentifier)) {
|
if (!AllocateLocallyUniqueId(&sourceContext.SourceIdentifier)) {
|
||||||
error("AllocateLocallyUniqueId failed, error:%d", GetLastError());
|
error("AllocateLocallyUniqueId failed, error:%d", GetLastError());
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = LsaLogonUser(lsa_handle,
|
if ((ret = LsaLogonUser(lsa_handle,
|
||||||
&originName,
|
&originName,
|
||||||
Network,
|
Network,
|
||||||
auth_package_id,
|
auth_package_id,
|
||||||
logon_info,
|
logon_info_w,
|
||||||
logon_info_size,
|
logon_info_size * sizeof(wchar_t),
|
||||||
NULL,
|
NULL,
|
||||||
&sourceContext,
|
&sourceContext,
|
||||||
&pProfile,
|
&pProfile,
|
||||||
|
@ -299,8 +305,8 @@ process_custom_lsa_auth(char* user, const char* pwd, char* lsa_pkg)
|
||||||
&logonId,
|
&logonId,
|
||||||
&token,
|
&token,
|
||||||
"as,
|
"as,
|
||||||
&subStatus)) != STATUS_SUCCESS) {
|
&subStatus)) != STATUS_SUCCESS) {
|
||||||
if(ret == STATUS_ACCOUNT_RESTRICTION)
|
if (ret == STATUS_ACCOUNT_RESTRICTION)
|
||||||
error("LsaLogonUser failed, error:%x subStatus:%ld", ret, subStatus);
|
error("LsaLogonUser failed, error:%x subStatus:%ld", ret, subStatus);
|
||||||
else
|
else
|
||||||
error("LsaLogonUser failed error:%x", ret);
|
error("LsaLogonUser failed error:%x", ret);
|
||||||
|
@ -308,19 +314,17 @@ process_custom_lsa_auth(char* user, const char* pwd, char* lsa_pkg)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug3("LSA auth request is successful for user:%s ", user);
|
||||||
retVal = 0;
|
retVal = 0;
|
||||||
done:
|
done:
|
||||||
/* delete allocated memory*/
|
|
||||||
if (lsa_handle)
|
if (lsa_handle)
|
||||||
LsaDeregisterLogonProcess(lsa_handle);
|
LsaDeregisterLogonProcess(lsa_handle);
|
||||||
if (logon_info)
|
|
||||||
free(logon_info);
|
|
||||||
if (pProfile)
|
if (pProfile)
|
||||||
LsaFreeReturnBuffer(pProfile);
|
LsaFreeReturnBuffer(pProfile);
|
||||||
if (userw)
|
if (logon_info)
|
||||||
free(userw);
|
free(logon_info);
|
||||||
if (pwdw)
|
if (logon_info_w)
|
||||||
free(pwdw);
|
free(logon_info_w);
|
||||||
|
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,8 @@
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
#include <Lm.h>
|
#include <Lm.h>
|
||||||
|
#include <sddl.h>
|
||||||
|
|
||||||
#include "inc\utf.h"
|
#include "inc\utf.h"
|
||||||
#include "misc_internal.h"
|
#include "misc_internal.h"
|
||||||
|
|
||||||
|
@ -163,15 +165,19 @@ create_prgdata_ssh_folder()
|
||||||
char ssh_cfg_dir[PATH_MAX] = { 0, };
|
char ssh_cfg_dir[PATH_MAX] = { 0, };
|
||||||
strcpy_s(ssh_cfg_dir, _countof(ssh_cfg_dir), get_program_data_path());
|
strcpy_s(ssh_cfg_dir, _countof(ssh_cfg_dir), get_program_data_path());
|
||||||
strcat_s(ssh_cfg_dir, _countof(ssh_cfg_dir), "\\ssh");
|
strcat_s(ssh_cfg_dir, _countof(ssh_cfg_dir), "\\ssh");
|
||||||
if (create_directory_withsddl(ssh_cfg_dir, "O:BAD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;0x1200a9;;;AU)") < 0)
|
if (create_directory_withsddl(ssh_cfg_dir, "O:BAD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;0x1200a9;;;AU)") < 0) {
|
||||||
fatal("failed to create %s", ssh_cfg_dir);
|
printf("failed to create %s", ssh_cfg_dir);
|
||||||
|
exit(255);
|
||||||
|
}
|
||||||
|
|
||||||
/* create logs folder */
|
/* create logs folder */
|
||||||
char logs_dir[PATH_MAX] = { 0, };
|
char logs_dir[PATH_MAX] = { 0, };
|
||||||
strcat_s(logs_dir, _countof(logs_dir), ssh_cfg_dir);
|
strcat_s(logs_dir, _countof(logs_dir), ssh_cfg_dir);
|
||||||
strcat_s(logs_dir, _countof(logs_dir), "\\logs");
|
strcat_s(logs_dir, _countof(logs_dir), "\\logs");
|
||||||
if (create_directory_withsddl(logs_dir, "O:BAD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)") < 0)
|
if (create_directory_withsddl(logs_dir, "O:BAD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)") < 0) {
|
||||||
fatal("failed to create %s", logs_dir);
|
printf("failed to create %s", logs_dir);
|
||||||
|
exit(255);
|
||||||
|
}
|
||||||
|
|
||||||
/* COPY sshd_config_default to %programData%\openssh\sshd_config */
|
/* COPY sshd_config_default to %programData%\openssh\sshd_config */
|
||||||
char sshd_config_path[PATH_MAX] = { 0, };
|
char sshd_config_path[PATH_MAX] = { 0, };
|
||||||
|
@ -183,16 +189,47 @@ create_prgdata_ssh_folder()
|
||||||
strcat_s(sshd_config_default_path, _countof(sshd_config_default_path), w32_programdir());
|
strcat_s(sshd_config_default_path, _countof(sshd_config_default_path), w32_programdir());
|
||||||
strcat_s(sshd_config_default_path, _countof(sshd_config_default_path), "\\sshd_config_default");
|
strcat_s(sshd_config_default_path, _countof(sshd_config_default_path), "\\sshd_config_default");
|
||||||
|
|
||||||
if (copy_file(sshd_config_default_path, sshd_config_path) < 0)
|
if (copy_file(sshd_config_default_path, sshd_config_path) < 0) {
|
||||||
fatal("Failed to copy %s to %s, error:%d", sshd_config_default_path, sshd_config_path, GetLastError());
|
printf("Failed to copy %s to %s, error:%d", sshd_config_default_path, sshd_config_path, GetLastError());
|
||||||
|
exit(255);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Create HKLM\Software\OpenSSH windows registry key */
|
||||||
|
static void
|
||||||
|
create_openssh_registry_key()
|
||||||
|
{
|
||||||
|
HKEY ssh_registry_root = NULL;
|
||||||
|
wchar_t* sddl_str;
|
||||||
|
SECURITY_ATTRIBUTES sa;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
|
||||||
|
sa.nLength = sizeof(sa);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SDDL - FullAcess to System and Builtin/Admins and restricted access to Authenticated users
|
||||||
|
* 0x12019b - FILE_GENERIC_READ/WRITE minus FILE_CREATE_PIPE_INSTANCE
|
||||||
|
*/
|
||||||
|
sddl_str = L"D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;0x12019b;;;AU)";
|
||||||
|
if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(sddl_str, SDDL_REVISION_1, &sa.lpSecurityDescriptor, &sa.nLength)) {
|
||||||
|
printf("cannot convert sddl ERROR:%d", GetLastError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((r = RegCreateKeyExW(HKEY_LOCAL_MACHINE, SSH_REGISTRY_ROOT, 0, 0, 0, KEY_WRITE, &sa, &ssh_registry_root, 0)) == ERROR_SUCCESS)
|
||||||
|
RegCloseKey(ssh_registry_root);
|
||||||
|
else
|
||||||
|
printf("cannot create ssh root reg key, ERROR:%d", r);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
prereq_setup()
|
prereq_setup()
|
||||||
{
|
{
|
||||||
create_prgdata_ssh_folder();
|
create_prgdata_ssh_folder();
|
||||||
generate_host_keys();
|
generate_host_keys();
|
||||||
|
create_openssh_registry_key();
|
||||||
}
|
}
|
||||||
|
|
||||||
int sshd_main(int argc, wchar_t **wargv) {
|
int sshd_main(int argc, wchar_t **wargv) {
|
||||||
|
@ -201,8 +238,11 @@ int sshd_main(int argc, wchar_t **wargv) {
|
||||||
_set_invalid_parameter_handler(invalid_parameter_handler);
|
_set_invalid_parameter_handler(invalid_parameter_handler);
|
||||||
|
|
||||||
if (argc) {
|
if (argc) {
|
||||||
if ((argv = malloc(argc * sizeof(char*))) == NULL)
|
if ((argv = malloc(argc * sizeof(char*))) == NULL) {
|
||||||
fatal("out of memory");
|
printf("out of memory");
|
||||||
|
exit(255);
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < argc; i++)
|
for (i = 0; i < argc; i++)
|
||||||
argv[i] = utf16_to_utf8(wargv[i]);
|
argv[i] = utf16_to_utf8(wargv[i]);
|
||||||
}
|
}
|
||||||
|
|
2
sftp.c
2
sftp.c
|
@ -397,7 +397,7 @@ make_absolute(char *p, const char *pwd)
|
||||||
* Need to follow up with community if this makes sense in common code
|
* Need to follow up with community if this makes sense in common code
|
||||||
*/
|
*/
|
||||||
char *s1, *s2;
|
char *s1, *s2;
|
||||||
if (p && p[0] != '/' && (p[0] == '\0' || p[1] != ':')) {
|
if (!is_absolute_path(p)) {
|
||||||
abs_str = path_append(pwd, p);
|
abs_str = path_append(pwd, p);
|
||||||
free(p);
|
free(p);
|
||||||
p = abs_str;
|
p = abs_str;
|
||||||
|
|
6
sshd.c
6
sshd.c
|
@ -774,7 +774,7 @@ privsep_preauth(Authctxt *authctxt)
|
||||||
else {
|
else {
|
||||||
char** argv = privsep_child_cmdline(0);
|
char** argv = privsep_child_cmdline(0);
|
||||||
if (__posix_spawn_asuser(&pid, argv[0], &actions, NULL, argv, NULL, SSH_PRIVSEP_USER) != 0)
|
if (__posix_spawn_asuser(&pid, argv[0], &actions, NULL, argv, NULL, SSH_PRIVSEP_USER) != 0)
|
||||||
error("posix_spawn failed");
|
error("%s, posix_spawn failed", __func__);
|
||||||
posix_spawn_file_actions_destroy(&actions);
|
posix_spawn_file_actions_destroy(&actions);
|
||||||
}
|
}
|
||||||
close(pmonitor->m_recvfd);
|
close(pmonitor->m_recvfd);
|
||||||
|
@ -880,7 +880,7 @@ privsep_postauth(Authctxt *authctxt)
|
||||||
else {
|
else {
|
||||||
char** argv = privsep_child_cmdline(1);
|
char** argv = privsep_child_cmdline(1);
|
||||||
if (__posix_spawn_asuser(&pmonitor->m_pid, argv[0], &actions, NULL, argv, NULL, authctxt->pw->pw_name) != 0)
|
if (__posix_spawn_asuser(&pmonitor->m_pid, argv[0], &actions, NULL, argv, NULL, authctxt->pw->pw_name) != 0)
|
||||||
error("posix_spawn failed");
|
error("%s, posix_spawn failed", __func__);
|
||||||
posix_spawn_file_actions_destroy(&actions);
|
posix_spawn_file_actions_destroy(&actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1545,7 +1545,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
|
||||||
error("posix_spawn initialization failed");
|
error("posix_spawn initialization failed");
|
||||||
else {
|
else {
|
||||||
if (posix_spawn(&pid, rexec_argv[0], &actions, &attributes, rexec_argv, NULL) != 0)
|
if (posix_spawn(&pid, rexec_argv[0], &actions, &attributes, rexec_argv, NULL) != 0)
|
||||||
error("posix_spawn failed");
|
error("%s, posix_spawn failed", __func__);
|
||||||
posix_spawn_file_actions_destroy(&actions);
|
posix_spawn_file_actions_destroy(&actions);
|
||||||
posix_spawnattr_destroy(&attributes);
|
posix_spawnattr_destroy(&attributes);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue