forked from dannydulai/xl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
155 lines (129 loc) · 4.79 KB
/
main.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
/*
* Danny Dulai
*
* Simple, transparent screen locker in X11
*/
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <crypt.h>
#include <string.h>
#include <pwd.h>
#include <security/pam_appl.h>
#include <security/pam_misc.h>
/**
* @brief This function performs a conversation between our application and the module.
* It receives an array of messages in the parameters (set by the module) and sets
* the array of responses in the parameters with the appropriate content.
* For example, if the module calls this function with a message "login:" we are expected
* to set the firs response with the username
*
* @param num_msg Number of messages from the module
* @param msg Array of messages (set by the module, should not be modified)
* @param resp Array of responses this function must set
* @param appdata_ptr Pointer to additional data. The pointer received is that specified
* in the pam_conv structure below.
*
* @return PAM return code
*/
static char blank[] = "";
int conversation(int num_msg, const struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr)
{ /* We malloc an array of num_msg responses */
struct pam_response *array_resp = (struct pam_response *)malloc(
num_msg * sizeof(struct pam_response));
for (int i = 0; i < num_msg; i++) {
char *text = blank;
/* resp_retcode should be set to zero */
array_resp[i].resp_retcode = 0;
/* The message received from the module */
const char *msg_content = msg[i]->msg;
if (strncasecmp("pass",msg_content,4) == 0) {
text = appdata_ptr;
} else if (strncasecmp("user",msg_content,4) == 0) {
text = getlogin();
} else if (strncasecmp("login",msg_content,5) == 0) {
text = getlogin();
}
/* Malloc-ing the resp string of the i-th response */
array_resp[i].resp = (char *)malloc(strlen(text) + 1);
/* Writing password in the allocated string */
strcpy(array_resp[i].resp, text);
}
/* setting the param resp with our array of responses */
*resp = array_resp;
/* Here we return PAM_SUCCESS, which means that the conversation happened correctly.
* You should always check that, for example, the user didn't insert a NULL password etc */
return PAM_SUCCESS;
}
int
main(int argc, char *argv[])
{
Display *display;
Window root;
int len = 0, i;
XEvent ev;
char keybuffer[256], *passwd = NULL;
if (argc > 1) {
setenv("XLPASSWD", argv[1], 1);
execl("/proc/self/exe", argv[0], NULL);
fprintf(stderr, "failed to execute self, use XLPASSWD environment\n");
exit(1);
} else if ((passwd = getenv("XLPASSWD"))) {
passwd = strdup(crypt(passwd, "ax"));
}
if (passwd && (strlen(passwd) < 2)) {
fprintf(stderr, "passwd too short\n");
exit(1);
}
if ((display = XOpenDisplay(NULL)) == NULL) {
fprintf(stderr, "could not connect to $DISPLAY\n");
exit(1);
}
root = DefaultRootWindow(display);
XGrabPointer(display, root, 1, ButtonPress, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
XGrabKeyboard(display, root, 0, GrabModeAsync, GrabModeAsync, CurrentTime);
XSelectInput(display, root, KeyPressMask);
while (XNextEvent(display, &ev), 1) {
if (ev.type == KeyPress) {
KeySym keysym;
XComposeStatus compose;
if (len > sizeof(keybuffer)-10)
len = 0;
i = XLookupString(&ev.xkey, keybuffer+len, 10, &keysym, &compose);
if (keysym == XK_Return) {
keybuffer[len] = 0;
if (len && passwd && !strcmp(crypt(keybuffer, passwd), passwd)) {
XUngrabKeyboard(display, CurrentTime);
XUngrabPointer(display, CurrentTime);
exit(0);
} else if (len && (passwd == NULL)) {
int iss;
pam_handle_t *pamh = NULL;
struct pam_conv pam_convo = {
conversation, keybuffer };
iss = pam_start("system-auth",(const char*)getlogin(), &pam_convo, &pamh);
if (iss != PAM_SUCCESS) {
printf("pam_start error %s\n",pam_strerror(pamh,iss));
}
iss = pam_authenticate(pamh,PAM_DISALLOW_NULL_AUTHTOK);
/* if (iss != PAM_SUCCESS) {
printf("pam_authenticate error %s\n",pam_strerror(pamh,iss));
} */
pam_end(pamh,iss);
if (iss == PAM_SUCCESS) {
XUngrabKeyboard(display, CurrentTime);
XUngrabPointer(display, CurrentTime);
exit(0);
}
len = 0;
} else
len = 0;
} else
len += i;
}
}
}