|
20 | 20 | #include <string.h>
|
21 | 21 | #include <sys/types.h>
|
22 | 22 | #include <sys/wait.h>
|
| 23 | +#include <spawn.h> |
23 | 24 | #include <mysql/plugin_auth.h>
|
24 | 25 | #include "auth_pam_tool.h"
|
25 | 26 | #include <my_global.h>
|
@@ -51,65 +52,51 @@ static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
|
51 | 52 | unsigned char field, *pkt;
|
52 | 53 | unsigned int n_sleep= 0;
|
53 | 54 | useconds_t sleep_time= 100;
|
| 55 | + posix_spawn_file_actions_t file_actions; |
| 56 | + char toolpath[FN_REFLEN]; |
| 57 | + size_t plugin_dir_len= strlen(opt_plugin_dir); |
| 58 | + char *const argv[2]= {toolpath, 0}; |
| 59 | + int res; |
54 | 60 |
|
55 | 61 | PAM_DEBUG((stderr, "PAM: opening pipes.\n"));
|
56 | 62 | if (pipe(p_to_c) < 0 || pipe(c_to_p) < 0)
|
57 | 63 | {
|
58 |
| - /* Error creating pipes. */ |
| 64 | + my_printf_error(ENOEXEC, "pam: cannot create pipes (errno: %M)", |
| 65 | + ME_ERROR_LOG_ONLY, errno); |
59 | 66 | return CR_ERROR;
|
60 | 67 | }
|
61 |
| - PAM_DEBUG((stderr, "PAM: forking.\n")); |
62 |
| - if ((proc_id= fork()) < 0) |
63 |
| - { |
64 |
| - /* Error forking. */ |
65 |
| - close(p_to_c[0]); |
66 |
| - close(c_to_p[1]); |
67 |
| - goto error_ret; |
68 |
| - } |
69 | 68 |
|
70 |
| - if (proc_id == 0) |
| 69 | + if (plugin_dir_len + tool_name_len + 2 > sizeof(toolpath)) |
71 | 70 | {
|
72 |
| - /* The 'sandbox' process started. */ |
73 |
| - char toolpath[FN_REFLEN]; |
74 |
| - size_t plugin_dir_len= strlen(opt_plugin_dir); |
75 |
| - |
76 |
| - PAM_DEBUG((stderr, "PAM: Child process prepares pipes.\n")); |
77 |
| - |
78 |
| - if (close(p_to_c[1]) < 0 || |
79 |
| - close(c_to_p[0]) < 0 || |
80 |
| - dup2(p_to_c[0], 0) < 0 || /* Parent's pipe to STDIN. */ |
81 |
| - dup2(c_to_p[1], 1) < 0) /* Sandbox's pipe to STDOUT. */ |
82 |
| - { |
83 |
| - exit(-1); |
84 |
| - } |
| 71 | + my_printf_error(ENOEXEC, "pam: too long path to <plugindir>/%s", |
| 72 | + ME_ERROR_LOG_ONLY, tool_name); |
| 73 | + return CR_ERROR; |
| 74 | + } |
85 | 75 |
|
86 |
| - PAM_DEBUG((stderr, "PAM: check tool directory: %s, %s.\n", |
87 |
| - opt_plugin_dir, tool_name)); |
88 |
| - if (plugin_dir_len + tool_name_len + 2 > sizeof(toolpath)) |
89 |
| - { |
90 |
| - /* Tool path too long. */ |
91 |
| - exit(-1); |
92 |
| - } |
| 76 | + memcpy(toolpath, opt_plugin_dir, plugin_dir_len); |
| 77 | + if (plugin_dir_len && toolpath[plugin_dir_len-1] != FN_LIBCHAR) |
| 78 | + toolpath[plugin_dir_len++]= FN_LIBCHAR; |
| 79 | + memcpy(toolpath+plugin_dir_len, tool_name, tool_name_len+1); |
93 | 80 |
|
94 |
| - memcpy(toolpath, opt_plugin_dir, plugin_dir_len); |
95 |
| - if (plugin_dir_len && toolpath[plugin_dir_len-1] != FN_LIBCHAR) |
96 |
| - toolpath[plugin_dir_len++]= FN_LIBCHAR; |
97 |
| - memcpy(toolpath+plugin_dir_len, tool_name, tool_name_len+1); |
98 |
| - |
99 |
| - PAM_DEBUG((stderr, "PAM: execute pam sandbox [%s].\n", toolpath)); |
100 |
| - (void) execl(toolpath, toolpath, NULL); |
101 |
| - PAM_DEBUG((stderr, "PAM: exec() failed.\n")); |
102 |
| - my_printf_error(1, "PAM: Cannot execute %s (errno: %M)", ME_ERROR_LOG_ONLY, |
103 |
| - toolpath, errno); |
104 |
| - exit(-1); |
105 |
| - } |
| 81 | + PAM_DEBUG((stderr, "PAM: forking %s\n", toolpath)); |
| 82 | + res= posix_spawn_file_actions_init(&file_actions) || |
| 83 | + posix_spawn_file_actions_addclose(&file_actions, p_to_c[1]) || |
| 84 | + posix_spawn_file_actions_addclose(&file_actions, c_to_p[0]) || |
| 85 | + posix_spawn_file_actions_adddup2(&file_actions, p_to_c[0], 0) || |
| 86 | + posix_spawn_file_actions_adddup2(&file_actions, c_to_p[1], 1) || |
| 87 | + posix_spawn(&proc_id, toolpath, &file_actions, NULL, argv, NULL); |
106 | 88 |
|
107 | 89 | /* Parent process continues. */
|
| 90 | + posix_spawn_file_actions_destroy(&file_actions); |
| 91 | + close(p_to_c[0]); |
| 92 | + close(c_to_p[1]); |
108 | 93 |
|
109 |
| - PAM_DEBUG((stderr, "PAM: parent continues.\n")); |
110 |
| - if (close(p_to_c[0]) < 0 || |
111 |
| - close(c_to_p[1]) < 0) |
| 94 | + if (res) |
| 95 | + { |
| 96 | + my_printf_error(ENOEXEC, "pam: cannot exec %s (errno: %M)", |
| 97 | + ME_ERROR_LOG_ONLY, toolpath, errno); |
112 | 98 | goto error_ret;
|
| 99 | + } |
113 | 100 |
|
114 | 101 | /* no user name yet ? read the client handshake packet with the user name */
|
115 | 102 | if (info->user_name == 0)
|
|
0 commit comments