]>
Commit | Line | Data |
---|---|---|
1631c5a9 DM |
1 | #include <stdlib.h> |
2 | #include <stdio.h> | |
3 | #include <string.h> | |
4 | #include <sys/types.h> | |
5 | #include <sys/socket.h> | |
6 | #include <netdb.h> | |
7 | ||
8 | #include "spiceterm.h" | |
9 | ||
10 | static char *auth_path = "/"; | |
11 | static char *auth_perm = "Sys.Console"; | |
12 | ||
13 | static char * | |
14 | urlencode(char *buf, const char *value) | |
15 | { | |
16 | static const char *hexchar = "0123456789abcdef"; | |
17 | char *p = buf; | |
18 | int i; | |
19 | int l = strlen(value); | |
20 | for (i = 0; i < l; i++) { | |
21 | char c = value[i]; | |
22 | if (('a' <= c && c <= 'z') || | |
23 | ('A' <= c && c <= 'Z') || | |
24 | ('0' <= c && c <= '9')) { | |
25 | *p++ = c; | |
26 | } else if (c == 32) { | |
27 | *p++ = '+'; | |
28 | } else { | |
29 | *p++ = '%'; | |
30 | *p++ = hexchar[c >> 4]; | |
31 | *p++ = hexchar[c & 15]; | |
32 | } | |
33 | } | |
34 | *p = 0; | |
35 | ||
36 | return p; | |
37 | } | |
38 | ||
39 | int | |
40 | pve_auth_verify(const char *clientip, const char *username, const char *passwd) | |
41 | { | |
42 | struct sockaddr_in server; | |
43 | ||
44 | int sfd = socket(AF_INET, SOCK_STREAM, 0); | |
45 | if (sfd == -1) { | |
46 | perror("pve_auth_verify: socket failed"); | |
47 | return -1; | |
48 | } | |
49 | ||
50 | struct hostent *he; | |
51 | if ((he = gethostbyname("localhost")) == NULL) { | |
52 | fprintf(stderr, "pve_auth_verify: error resolving hostname\n"); | |
53 | goto err; | |
54 | } | |
55 | ||
56 | memcpy(&server.sin_addr, he->h_addr_list[0], he->h_length); | |
57 | server.sin_family = AF_INET; | |
58 | server.sin_port = htons(85); | |
59 | ||
60 | if (connect(sfd, (struct sockaddr *)&server, sizeof(server))) { | |
61 | perror("pve_auth_verify: error connecting to server"); | |
62 | goto err; | |
63 | } | |
64 | ||
65 | char buf[8192]; | |
66 | char form[8192]; | |
67 | ||
68 | char *p = form; | |
69 | p = urlencode(p, "username"); | |
70 | *p++ = '='; | |
71 | p = urlencode(p, username); | |
72 | ||
73 | *p++ = '&'; | |
74 | p = urlencode(p, "password"); | |
75 | *p++ = '='; | |
76 | p = urlencode(p, passwd); | |
77 | ||
78 | *p++ = '&'; | |
79 | p = urlencode(p, "path"); | |
80 | *p++ = '='; | |
81 | p = urlencode(p, auth_path); | |
82 | ||
83 | *p++ = '&'; | |
84 | p = urlencode(p, "privs"); | |
85 | *p++ = '='; | |
86 | p = urlencode(p, auth_perm); | |
87 | ||
88 | sprintf(buf, "POST /api2/json/access/ticket HTTP/1.1\n" | |
89 | "Host: localhost:85\n" | |
90 | "Connection: close\n" | |
91 | "PVEClientIP: %s\n" | |
92 | "Content-Type: application/x-www-form-urlencoded\n" | |
93 | "Content-Length: %zd\n\n%s\n", clientip, strlen(form), form); | |
94 | ssize_t len = strlen(buf); | |
95 | ssize_t sb = send(sfd, buf, len, 0); | |
96 | if (sb < 0) { | |
97 | perror("pve_auth_verify: send failed"); | |
98 | goto err; | |
99 | } | |
100 | if (sb != len) { | |
101 | fprintf(stderr, "pve_auth_verify: partial send error\n"); | |
102 | goto err; | |
103 | } | |
104 | ||
105 | len = recv(sfd, buf, sizeof(buf) - 1, 0); | |
106 | if (len < 0) { | |
107 | perror("pve_auth_verify: recv failed"); | |
108 | goto err; | |
109 | } | |
110 | ||
111 | buf[len] = 0; | |
112 | ||
113 | //printf("DATA:%s\n", buf); | |
114 | ||
115 | shutdown(sfd, SHUT_RDWR); | |
116 | ||
117 | if (!strncmp(buf, "HTTP/1.1 200 OK", 15)) { | |
118 | return 0; | |
119 | } | |
120 | ||
121 | char *firstline = strtok(buf, "\n"); | |
122 | ||
123 | fprintf(stderr, "auth failed: %s\n", firstline); | |
124 | ||
125 | return -1; | |
126 | ||
127 | err: | |
128 | shutdown(sfd, SHUT_RDWR); | |
129 | return -1; | |
130 | } |