gekmihesg
Anmeldungsdatum: 6. Mai 2009
Beiträge: Zähle...
|
Ich habe folgendes Skript:
| #!/bin/bash
u=$1
p=$2
shift 2
echo "$p" | su "$u" -c "$@"
|
Das Ganze ist eigentlich nur ein Wrapper für su der ermöglichen soll, dass man das Passwort auch direkt als Parameter angeben kann. Endziel ist dann, dass dem Benutzer über ein Webfrontend bestimmte Funktionen zur Verfügung gestellt werden können, die aber unter seinen Rechten ausgeführt werden. Das liefert aber nur eine Fehlermeldung:
su: must be run from a terminal sudo -u BENUTZER ist meines Erachtens keine Alternative. Dazu müsste man www-data erlauben das Skript ohne Passwortabfrage auszuführen und das Benutzerpasswort wird nicht abgefragt.
Hat jemand vielleicht einen anderen Ansatz für mich?
|
schmidti411
Anmeldungsdatum: 24. Oktober 2007
Beiträge: 152
Wohnort: Berlin
|
Es ist nicht möglich an su das Passwort über eine pipe ('|') zu übergeben. Su fragt das Passwort immer über das Terminal ab. Ein lesen von einer Pipe oder einem File ist da nicht möglich. Das wird über ein ioctl überprüft, welches bei einer Pipe oder einem File mit ENOTTY quittiert wird. Du könntest ein kleines C Programm schreiben, welches dein Befehl unter dem richtigen User ausführt und welches mit SUID-Bit im Filesystem abgelegt wird. Evtl. gibt es auch noch ein su Alternative... Ich weiß aber leider keine... Gruß, Schmidti!
|
barcc
Anmeldungsdatum: 13. Juli 2007
Beiträge: 696
Wohnort: Dortmund
|
Hallo, sudo kann das Passwort über die Standardeingabe lesen mit der Option -S :
echo "$p" | sudo -u "$u" -S -- "$@" Gruß, barcc
|
theinlein
Anmeldungsdatum: 29. Dezember 2007
Beiträge: 1279
|
Hallo, es gibt noch expect ... Eingabe über Pseudo-Terminal vortäuschen, um so alle sonstigen gängigen Tools mit Passwortabfrage verwenden zu können http://en.wikipedia.org/wiki/Expect
|
gekmihesg
(Themenstarter)
Anmeldungsdatum: 6. Mai 2009
Beiträge: 106
|
Danke für die Antworten! Hab mich für das C-Programm entschieden:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 | #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <syslog.h>
#include <pwd.h>
#include <shadow.h>
#include <crypt.h>
#define APPLICATION_NAME "uexec"
void usage() {
printf("Usage: %s USERNAME PASSWORD COMMAND [PARAMETER [...]]\n", APPLICATION_NAME);
}
int check_pass(const char *user, const char *pass) {
struct spwd *shadow;
char *crypted;
int result;
if ((shadow = getspnam(user)) == NULL)
return 0;
crypted = crypt(pass, shadow->sp_pwdp);
result = strcmp(crypted, shadow->sp_pwdp) == 0;
free(crypted);
return result;
}
int main(int argc, char *argv[]) {
if (argc <= 3) {
usage();
exit(2);
}
int i;
int arg = 3;
char *user = argv[1];
char *pass = argv[2];
char *acmd = argv[3];
char *cmd;
struct passwd *p;
if (atoi(user) > 0 && (p = getpwuid(atoi(user))) != NULL) {
user = p->pw_name;
}
if (!check_pass(user, pass)) {
openlog(APPLICATION_NAME, LOG_PID, LOG_AUTH);
syslog(LOG_WARNING, "Incorrect password for '%s'", user);
closelog();
sleep(2);
fputs("Login incorrect\n", stderr);
exit(1);
}
for (i = 0; arg < argc; i ++) {
if (acmd[i] == '\0') {
if (arg < argc - 1)
acmd[i] = ' ';
arg ++;
}
}
cmd = (char*)malloc(strlen(user) + i + 12);
sprintf(cmd, "sudo -u %s -- %s", user, acmd);
i = system(cmd);
free(cmd);
return i;
}
|
gcc uexec.c -o uexec -lcrypt && sudo chown root.root uexec && sudo chmod u+s uexec Benutzung: uexec USERNAME PASSWORD COMMAND [PARAMETER [...]], wobei USERNAME auch die uid sein kann. Meine C-Kenntnisse sind leider etwas eingerostet, solle ich also irgendwo totalen Blödsinn fabriziert haben, bitte dringend Bescheid sagen! Bin sowieso überrascht, dass ich das tatsächlich hingekriegt hab 😉
|
gekmihesg
(Themenstarter)
Anmeldungsdatum: 6. Mai 2009
Beiträge: 106
|
Eine Sache ist mir gerade selber aufgefallen:
Wenn der User keine Shell hat (z.B. /bin/false) dann könnte er über dieses Programm über einen fremden Account einfach mit beliebige Programme starten. Das sollte man dringend unterbinden. Außerdem liefert das keine Ausgabe: uexec testuser testpass bash -c 'echo test' zeigt eine Leerzeile, uexec testuser testpass echo test und sudo -u test -- bash -c 'echo test' geben "test" aus.
Woran liegt das?
|
barcc
Anmeldungsdatum: 13. Juli 2007
Beiträge: 696
Wohnort: Dortmund
|
Wenn ich dein Programm richtig verstanden habe, hebelst du die Rechteverwaltung aus um dann das Passwort selbst zu überprüfen. Bei sowas habe ich eher ein ungutes Gefühl, obwohl ich zugeben muss, dass ich davon zu wenig verstehe, um zu beurteilen, ob die Vorgehensweise fehlerhaft ist. Beim ersten Beispiel im zweiten Abschnitt ist das Problem, wie du die Argumente zusammenbaust. Dabei gehen die ' verloren. Lass dir doch einfach mal den Inhalt von cmd ausgeben, dann siehst du es.
|
theinlein
Anmeldungsdatum: 29. Dezember 2007
Beiträge: 1279
|
Du hast ja ein typisches Problem von Web-Fronends angeschnitten. Da du dich aber für die sudo-Variante entschieden hast und das Passwort per Commandline mitgibst, ist das C-Programm doch unnötig. (Ich gehe davon aus, dass du keinen Web-Frontend hast, der in C geschrieben ist ☺ ) Mit der Wahl von sudo erbst du die Sicherheit eines sudo (je nach Konfiguration ist das gut genug für dich oder eben nicht - dein Argument mit demjenigen, der keinen Account hat zieht ja nur, wenn einer ein Passwort knackt und das Problem hast du immer).
Es bleibt natürlich die Vorsorge, auf welchem Wege das Passwort dahin kommt und wo es dabei beobachtbar ist.
|
schmidti411
Anmeldungsdatum: 24. Oktober 2007
Beiträge: 152
Wohnort: Berlin
|
Ich finde den Abschnitt if (atoi(user) > 0 && (p = getpwuid(atoi(user))) != NULL) {
user = p->pw_name;
} nicht so schick. Angenommen du hast mehrer web-Accounts durchnummeriert von web1 bis web[n] dann würde dein Programm immer denken, dass 1 bzw. n die UID ist und nicht der Benutzername. Du solltest daher überprüfen, ob user nur aus Zahlen besteht, da es erst dann eine UID sein kann - oder du läßt UIDs als Userangabe gar nicht zu. Gruß, Schmidti
|
gekmihesg
(Themenstarter)
Anmeldungsdatum: 6. Mai 2009
Beiträge: 106
|
Ok, vergesst das C-Programm. Ist massiv unsicher! Es ignoriert alles was mit abgelaufenen Passwörtern zu tun hat.
Ich hab das nochmal neu aufgesetzt und die Authentifizierung über PAM geregelt. Ist aber noch nicht ganz fertig. @barcc:
Danke für den Hinweis, manchmal sieht man den Wald vor lauter Bäumen nicht. @theinlein:
Ich versteh nicht ganz was du meinst. Die sudo Variante allein, prüft doch nicht das Benutzerpasswort. Vielmehr würde sie ohne entsprechende sudoers Einträge das Passwort von www-data prüfen, dass der nicht hat, geschweige denn in der admin Gruppe ist. @schmidti411:
So wie ich das verstanden hab, liefert atoi 0 sobald ein [^0-9] im String vorkommt (was eigentlich ziemlich dumm ist). Aber in der neuen Version fliegt das sowieso raus.
|
gekmihesg
(Themenstarter)
Anmeldungsdatum: 6. Mai 2009
Beiträge: 106
|
Nach stundenlangem googeln und lesen der Sources von sudo und shadow läuft das Ganze jetzt über PAM, die Ausführung dann wieder mit sudo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240 | #ifndef CONV_HACK
#define CONV_HACK
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <pwd.h>
#include <errno.h>
#include <security/pam_appl.h>
#include <security/pam_ext.h>
#include <security/pam_misc.h>
/* defines */
#define APPLICATION_NAME "uexec"
#define PAM_S "su"
/* externals */
extern char *optarg;
extern int optind, opterr, optopt;
extern int errno;
/* prototypes */
void error(int errorlevel, char *fmt, ...) __attribute__((noreturn));
void pe(int errorlevel);
int restricted_shell(const char *shellstr);
int is_numeric(char *str);
#ifdef CONV_HACK
static int conv(int, const struct pam_message **, struct pam_response **, void *);
#endif
/* golbals */
#ifdef CONV_HACK
static struct pam_conv pam_c = { conv, 0};
#else
static struct pam_conv pam_c = { misc_conv, 0 };
#endif
pam_handle_t *pam_h = NULL;
char *user = NULL;
char *pass = NULL;
char *cmd = NULL;
char *shell = NULL;
void usage(int errorlevel) {
#ifdef CONV_HACK
printf("usage: %s [-u username|#uid] [-p password] [-s shell] [-c command] [-h]\n",
APPLICATION_NAME);
#else
printf("usage: %s [-u username|#uid] [-s shell] [-c command] [-h]\n",
APPLICATION_NAME);
#endif
exit(errorlevel);
}
int main(int argc, char **argv) {
struct passwd *olduser;
struct passwd *newuser;
int uid = getuid();
char opt;
int x;
if (geteuid())
error(1, "you must be suid root");
/* get current user */
olduser = getpwuid(uid);
if (!olduser)
exit(3); // should not happen
/* parse arguments */
#ifdef CONV_HACK
while ((opt = getopt(argc, argv, "u:s:c:p:h")) != -1) {
switch (opt) {
case 'p':
pass = optarg;
break;
#else
while ((opt = getopt(argc, argv, "u:s:c:h")) != -1) {
switch (opt) {
#endif
case 'u':
user = optarg;
break;
case 'c':
cmd = optarg;
break;
case 's':
shell = optarg;
break;
case 'h':
usage(0);
default:
usage(1);
}
}
/* check given user */
if (!user || !*user)
user = NULL;
else {
if (user[0] == '#') {
if (is_numeric(&user[1]))
newuser = getpwuid(atoi(&user[1]));
else
newuser = NULL;
} else
newuser = getpwnam(user);
if (newuser)
user = newuser->pw_name;
else
error(1, "unknown user: %s", user);
}
/* authenticate user */
pe(pam_start(PAM_S, user, &pam_c, &pam_h));
pe(pam_set_item(pam_h, PAM_RUSER, (const void *) olduser->pw_name));
pe(pam_authenticate(pam_h, PAM_DISALLOW_NULL_AUTHTOK));
if (!user) {
pe(pam_get_item(pam_h, PAM_USER, (const void **) &user));
if ((newuser = getpwnam(user)) == NULL)
error(3, "unknown user"); // should not happen
}
pam_end(pam_h, PAM_SUCCESS);
/* check user shell */
if (!(shell && *shell) || restricted_shell(newuser->pw_shell))
shell = newuser->pw_shell;
/* execute shell */
if (!cmd)
x = execlp("/usr/bin/sudo", "sudo", "-Hnu", newuser->pw_name, "--",
shell, NULL);
else
x = execlp("/usr/bin/sudo", "sudo", "-Hnu", newuser->pw_name, "--",
shell, "-c", cmd, NULL);
/* command execution failed, maybe sudo not found */
if (x == -1)
error(errno, "%s", strerror(errno));
/* should not be reached */
error(255, "unknown error");
}
/* implementations */
void error(int errorlevel, char *fmt, ...) {
va_list va;
va_start(va, fmt);
fprintf(stderr, "%s: ", APPLICATION_NAME);
vfprintf(stderr, fmt, va);
fputc('\n', stderr);
va_end(va);
exit(errorlevel);
}
void pe(int errorlevel) {
if (errorlevel != PAM_SUCCESS) {
error(2, "%s", pam_strerror(pam_h, errorlevel));
}
}
int restricted_shell(const char *shellstr) {
char *line;
setusershell();
while ((line = getusershell()) != NULL) {
if (*line != '#' && strcmp(line, shellstr) == 0) {
endusershell();
return 0;
}
}
endusershell();
return 1;
}
int is_numeric(char *str) {
while (*str) {
if (!isdigit(*str))
return 0;
str ++;
}
return 1;
}
#ifdef CONV_HACK
void zeromem(void *v, int n)
{
char *p, *ep;
for (p = v, ep = p + n; p < ep; p++)
*p = 0;
}
static int conv(int num_msg, const struct pam_message **msg, struct pam_response **response, void *appdata_ptr)
{
const struct pam_message *m;
struct pam_response *r, **s;
int n = num_msg;
char *p = NULL;
if (!(pass && *pass))
return misc_conv(num_msg, msg, response, appdata_ptr);
if ((*response = calloc(num_msg, sizeof(struct pam_response))) == NULL)
return PAM_CONV_ERR;
for (m = *msg, r = *response, n = num_msg; n --; m ++, r ++) {
if (p == NULL && m->msg_style == PAM_PROMPT_ECHO_OFF) {
/* assume pam asks for password */
if ((p = (char *)malloc(strlen(pass) + 1)) == NULL)
goto failed;
strcpy(p, pass);
r->resp = p;
break;
} else {
s = NULL;
if (misc_conv(1, &m, s, appdata_ptr) != PAM_SUCCESS)
goto failed;
memcpy(r, *s, sizeof(struct pam_response));
zeromem(*s, sizeof(struct pam_response));
free(s);
}
}
return PAM_SUCCESS;
failed:
for (r = *response, n = num_msg; n --; r ++) {
if (r->resp) {
zeromem(r->resp, strlen(r->resp));
free(r->resp);
}
zeromem(r, sizeof(struct pam_response));
}
free(*response);
*response = NULL;
return PAM_CONV_ERR;
}
#endif
|
gcc uexec.c -ouexec -lpam -lpam_misc && sudo chown root.root uexec && sudo chmod u+s uexec
usage: uexec [-u username|#uid] [-p password] [-s shell] [-c command] [-h]
Wenn man CONV_HACK nicht definiert, dann kann das Passwort nicht als Parameter übergeben werden. Wird aber von stdin gelesen, also echo pass | uexec -u user . Prinzipiell wird command jetzt in einer neuen Shell gestartet, wobei uexec den selben Regeln wie su folgt. Wenn man Benutzer oder Passwort nicht angibt wird entsprechend nachgefragt. Sicher sollte das jetzt alle mal sein, folgt ja den systemweiten Regeln von PAM und sudo, plus die Einschränkung mit der Shell.
|
gekmihesg
(Themenstarter)
Anmeldungsdatum: 6. Mai 2009
Beiträge: 106
|
Hat wohl keiner getestet... Funktioniert auf jeden Fall nicht.
Korrigierte Version: uexec.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | #ifndef UEXEC_H_
#define UEXEC_H_
#define CONVERSATION_HACK
//#undef CONVERSATION_HACK
#define APPLICATION_NAME "uexec"
#define PAM_S "su"
#define ERR_PROG 1
#define ERR_PAM 2
#define ERR_SYS 3
#define ERR_WEIRD 4 // should not happen
#define ROOT_UID 0
#define execshell(u, sh, ...) execlp("/usr/bin/sudo", "sudo", "-Hnu", u, "--", sh, __VA_ARGS__, NULL)
#endif
|
uexec.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248 | #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <pwd.h>
#include <errno.h>
#include <security/pam_appl.h>
#include <security/pam_ext.h>
#include <security/pam_misc.h>
#include "uexec.h"
/* prototypes */
void error(int errorlevel, char *fmt, ...) __attribute__((noreturn));
void pe(int errorlevel);
void se(int retval);
int restricted_shell(const char *shellstr);
int is_numeric(char *str);
void zeromem(void *v, int n);
#ifdef CONVERSATION_HACK
static int conv(int, const struct pam_message **, struct pam_response **, void *);
#endif
/* golbals */
#ifdef CONVERSATION_HACK
static struct pam_conv pam_c = { conv, 0};
#else
static struct pam_conv pam_c = { misc_conv, 0 };
#endif
pam_handle_t *pam_h = NULL;
char *user = NULL;
char *pass = NULL;
char *cmd = NULL;
char *shell = NULL;
void usage(int errorlevel) {
#ifdef CONVERSATION_HACK
printf("usage: %s [-u username|#uid] [-p password] [-s shell] [-c command] [-h]\n",
APPLICATION_NAME);
#else
printf("usage: %s [-u username|#uid] [-s shell] [-c command] [-h]\n",
APPLICATION_NAME);
#endif
exit(errorlevel);
}
int main(int argc, char **argv) {
struct passwd *olduser, *newuser = NULL;
const int uid = getuid();
char opt;
if (geteuid() != ROOT_UID)
error(ERR_PROG, "you must be suid root");
/* get current user */
if (!(olduser = getpwuid(uid)))
error(ERR_WEIRD, "current user does not exist");
/* parse arguments */
#ifdef CONVERSATION_HACK
while ((opt = getopt(argc, argv, "u:s:c:p:h")) != -1) {
switch (opt) {
case 'p':
pass = optarg;
break;
#else
while ((opt = getopt(argc, argv, "u:s:c:h")) != -1) {
switch (opt) {
#endif
case 'u':
user = optarg;
break;
case 'c':
cmd = optarg;
break;
case 's':
shell = optarg;
break;
case 'h':
usage(0);
default:
usage(ERR_PROG);
}
}
/* check given user */
if (!user || !*user)
user = NULL;
else {
if (user[0] == '#') {
if (is_numeric(&user[1]))
newuser = getpwuid(atoi(&user[1]));
else
newuser = NULL;
} else
newuser = getpwnam(user);
if (newuser)
user = newuser->pw_name;
else
error(ERR_PROG, "unknown user: %s", user);
}
/* authenticate user */
pe(pam_start(PAM_S, user, &pam_c, &pam_h));
pe(pam_set_item(pam_h, PAM_RUSER, olduser->pw_name));
pe(pam_authenticate(pam_h, PAM_DISALLOW_NULL_AUTHTOK));
/* password not needed any more */
if (pass && *pass)
zeromem(pass, strlen(pass));
/* user was not set, but we are here, so pam must have it */
if (!user) {
pe(pam_get_item(pam_h, PAM_USER, (const void **)&user));
if ((newuser = getpwnam(user)) == NULL)
error(ERR_WEIRD, "unknown user");
/* pam_end will kill user */
user = newuser->pw_name;
}
pam_end(pam_h, PAM_SUCCESS);
/* check user shell */
if (!(shell && *shell) || restricted_shell(newuser->pw_shell))
shell = newuser->pw_shell;
/* become real root */
se(setreuid(ROOT_UID, -1));
/* execute shell */
if (!cmd) {
se(chdir(newuser->pw_dir));
se(execshell(user, shell, "-i"));
}
else
se(execshell(user, shell, "-c", cmd));
/* should not be reached */
error(ERR_WEIRD, "unknown error");
}
/* implementations */
void error(int errorlevel, char *fmt, ...) {
va_list va;
va_start(va, fmt);
fprintf(stderr, "%s: ", APPLICATION_NAME);
vfprintf(stderr, fmt, va);
fputc('\n', stderr);
va_end(va);
exit(errorlevel);
}
void pe(int errorlevel) {
if (errorlevel != PAM_SUCCESS) {
error(ERR_PAM, "%s", pam_strerror(pam_h, errorlevel));
if (pam_h)
pam_end(pam_h, errorlevel);
}
}
void se(int retval) {
if (retval == -1)
error(ERR_SYS, "%s", strerror(errno));
}
int restricted_shell(const char *shellstr) {
char *line;
setusershell();
while ((line = getusershell()) != NULL) {
if (*line != '#' && strcmp(line, shellstr) == 0) {
endusershell();
return 0;
}
}
endusershell();
return 1;
}
int is_numeric(char *str) {
while (*str) {
if (!isdigit(*str))
return 0;
str ++;
}
return 1;
}
void zeromem(void *v, int n)
{
char *p, *ep;
for (p = v, ep = p + n; p < ep; p++)
*p = 0;
}
#ifdef CONVERSATION_HACK
/*
* automatically replies with password to first PAM_PROMPT_ECHO_OFF message and
* forwards all other messages (one by one) to misc_conv() and copies the response
*/
static int conv(int num_msg, const struct pam_message **msg, struct pam_response **response, void *appdata_ptr)
{
const struct pam_message *m;
struct pam_response *r, *s;
int n = num_msg;
char *p = NULL;
/* password not set, just let misc_conv do our job */
if (!(pass && *pass))
return misc_conv(num_msg, msg, response, appdata_ptr);
if ((*response = calloc(num_msg, sizeof(struct pam_response))) == NULL)
return PAM_CONV_ERR;
for (m = *msg, r = *response, n = num_msg; n --; m ++, r ++) {
if (p == NULL && m->msg_style == PAM_PROMPT_ECHO_OFF) {
/* assume pam asks for password */
if ((p = (char *)malloc(strlen(pass) + 1)) == NULL)
goto failed;
strcpy(p, pass);
r->resp = p;
break;
} else {
s = NULL;
/* let misc_conv process the current message */
if (misc_conv(1, &m, &s, appdata_ptr) != PAM_SUCCESS)
goto failed;
/* copy response to our real response and clean up */
memcpy(r, s, sizeof(struct pam_response));
zeromem(s, sizeof(struct pam_response));
free(s);
}
}
return PAM_SUCCESS;
failed:
for (r = *response, n = num_msg; n --; r ++) {
/* zero and free the response texts too */
if (r->resp) {
zeromem(r->resp, strlen(r->resp));
free(r->resp);
}
zeromem(r, sizeof(struct pam_response));
}
free(*response);
*response = NULL;
return PAM_CONV_ERR;
}
#endif
|
Makefile
CC = gcc
OBJECTS = uexec.o
LIBS = -lpam -lpam_misc
CFLAGS = -Wall -O3
BINDIR = $(DESTDIR)/usr/local/bin
NAME = uexec
cbg: $(OBJECTS)
$(CC) -o $(NAME) $(OBJECTS) $(LIBS)
%.o: %.c
$(CC) -c $(CFLAGS) $<
install:
install --mode=4755 $(NAME) $(BINDIR)/
clean:
@rm *.o $(NAME)
uninstall:
@rm $(BINDIR)/$(NAME)
|