]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (C) 1996-2023 The Squid Software Foundation and contributors | |
3 | * | |
4 | * Squid software is distributed under GPLv2+ license and includes | |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
7 | */ | |
8 | ||
9 | /* | |
10 | * basic_smb_auth - SMB proxy authentication module | |
11 | * Copyright (C) 1998 Richard Huveneers <richard@hekkihek.hacom.nl> | |
12 | * | |
13 | * This program is free software; you can redistribute it and/or modify | |
14 | * it under the terms of the GNU General Public License as published by | |
15 | * the Free Software Foundation; either version 2 of the License, or | |
16 | * (at your option) any later version. | |
17 | * | |
18 | * This program is distributed in the hope that it will be useful, | |
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
21 | * GNU General Public License for more details. | |
22 | * | |
23 | * You should have received a copy of the GNU General Public License | |
24 | * along with this program; if not, write to the Free Software | |
25 | */ | |
26 | ||
27 | #include "squid.h" | |
28 | #include "helper/protocol_defines.h" | |
29 | #include "rfc1738.h" | |
30 | #include "util.h" | |
31 | ||
32 | #include <cstring> | |
33 | ||
34 | #define NMB_UNICAST 1 | |
35 | #define NMB_BROADCAST 2 | |
36 | ||
37 | struct SMBDOMAIN { | |
38 | const char *name; /* domain name */ | |
39 | const char *sname; /* match this with user input */ | |
40 | const char *passthrough; /* pass-through authentication */ | |
41 | const char *nmbaddr; /* name service address */ | |
42 | int nmbcast; /* broadcast or unicast */ | |
43 | char *authshare; /* share name of auth file */ | |
44 | const char *authfile; /* pathname of auth file */ | |
45 | struct SMBDOMAIN *next; /* linked list */ | |
46 | }; | |
47 | ||
48 | struct SMBDOMAIN *firstdom = nullptr; | |
49 | struct SMBDOMAIN *lastdom = nullptr; | |
50 | ||
51 | /* | |
52 | * escape the backslash character, since it has a special meaning | |
53 | * to the read command of the bourne shell. | |
54 | */ | |
55 | ||
56 | static void | |
57 | print_esc(FILE * p, char *s) | |
58 | { | |
59 | char buf[HELPER_INPUT_BUFFER]; | |
60 | char *t; | |
61 | int i = 0; | |
62 | ||
63 | for (t = s; *t != '\0'; ++t) { | |
64 | /* | |
65 | * NP: The shell escaping permits 'i' to jump up to 2 octets per loop, | |
66 | * so ensure we have at least 3 free. | |
67 | */ | |
68 | if (i > HELPER_INPUT_BUFFER-3) { | |
69 | buf[i] = '\0'; | |
70 | (void) fputs(buf, p); | |
71 | i = 0; | |
72 | } | |
73 | if (*t == '\\') | |
74 | buf[i++] = '\\'; | |
75 | ||
76 | buf[i] = *t; | |
77 | ++i; | |
78 | } | |
79 | ||
80 | if (i > 0) { | |
81 | buf[i] = '\0'; | |
82 | (void) fputs(buf, p); | |
83 | } | |
84 | } | |
85 | ||
86 | int | |
87 | main(int argc, char *argv[]) | |
88 | { | |
89 | int i; | |
90 | char buf[HELPER_INPUT_BUFFER]; | |
91 | struct SMBDOMAIN *dom; | |
92 | char *s; | |
93 | char *user; | |
94 | char *pass; | |
95 | char *domname; | |
96 | FILE *p; | |
97 | const char *shcmd; | |
98 | ||
99 | /* make standard output line buffered */ | |
100 | if (setvbuf(stdout, nullptr, _IOLBF, 0) != 0) | |
101 | exit(EXIT_FAILURE); | |
102 | ||
103 | /* parse command line arguments */ | |
104 | for (i = 1; i < argc; ++i) { | |
105 | if (strcmp(argv[i], "-d") == 0) { | |
106 | debug_enabled = 1; | |
107 | continue; | |
108 | } | |
109 | /* the next options require an argument */ | |
110 | if (i + 1 == argc) | |
111 | break; | |
112 | ||
113 | if (strcmp(argv[i], "-W") == 0) { | |
114 | dom = static_cast<struct SMBDOMAIN *>(xmalloc(sizeof(struct SMBDOMAIN))); | |
115 | ||
116 | dom->name = dom->sname = argv[++i]; | |
117 | dom->passthrough = ""; | |
118 | dom->nmbaddr = ""; | |
119 | dom->nmbcast = NMB_BROADCAST; | |
120 | dom->authshare = (char *)"NETLOGON"; | |
121 | dom->authfile = "proxyauth"; | |
122 | dom->next = nullptr; | |
123 | ||
124 | /* append to linked list */ | |
125 | if (lastdom != nullptr) | |
126 | lastdom->next = dom; | |
127 | else | |
128 | firstdom = dom; | |
129 | ||
130 | lastdom = dom; | |
131 | continue; | |
132 | } | |
133 | if (strcmp(argv[i], "-w") == 0) { | |
134 | if (lastdom != nullptr) | |
135 | lastdom->sname = argv[++i]; | |
136 | continue; | |
137 | } | |
138 | if (strcmp(argv[i], "-P") == 0) { | |
139 | if (lastdom != nullptr) | |
140 | lastdom->passthrough = argv[++i]; | |
141 | continue; | |
142 | } | |
143 | if (strcmp(argv[i], "-B") == 0) { | |
144 | if (lastdom != nullptr) { | |
145 | lastdom->nmbaddr = argv[++i]; | |
146 | lastdom->nmbcast = NMB_BROADCAST; | |
147 | } | |
148 | continue; | |
149 | } | |
150 | if (strcmp(argv[i], "-U") == 0) { | |
151 | if (lastdom != nullptr) { | |
152 | lastdom->nmbaddr = argv[++i]; | |
153 | lastdom->nmbcast = NMB_UNICAST; | |
154 | } | |
155 | continue; | |
156 | } | |
157 | if (strcmp(argv[i], "-S") == 0) { | |
158 | if (lastdom != nullptr) { | |
159 | if ((lastdom->authshare = xstrdup(argv[++i])) == nullptr) | |
160 | exit(EXIT_FAILURE); | |
161 | ||
162 | /* convert backslashes to forward slashes */ | |
163 | for (s = lastdom->authshare; *s != '\0'; ++s) | |
164 | if (*s == '\\') | |
165 | *s = '/'; | |
166 | ||
167 | /* strip leading forward slash from share name */ | |
168 | if (*lastdom->authshare == '/') | |
169 | ++lastdom->authshare; | |
170 | ||
171 | if ((s = strchr(lastdom->authshare, '/')) != nullptr) { | |
172 | *s = '\0'; | |
173 | lastdom->authfile = s + 1; | |
174 | } | |
175 | } | |
176 | continue; | |
177 | } | |
178 | } | |
179 | ||
180 | shcmd = debug_enabled ? HELPERSCRIPT : HELPERSCRIPT " > /dev/null 2>&1"; | |
181 | ||
182 | while (fgets(buf, HELPER_INPUT_BUFFER, stdin) != nullptr) { | |
183 | ||
184 | if ((s = strchr(buf, '\n')) == nullptr) | |
185 | continue; | |
186 | *s = '\0'; | |
187 | ||
188 | if ((s = strchr(buf, ' ')) == nullptr) { | |
189 | SEND_ERR(""); | |
190 | continue; | |
191 | } | |
192 | *s = '\0'; | |
193 | ||
194 | user = buf; | |
195 | pass = s + 1; | |
196 | domname = nullptr; | |
197 | ||
198 | rfc1738_unescape(user); | |
199 | rfc1738_unescape(pass); | |
200 | ||
201 | if ((s = strchr(user, '\\')) != nullptr) { | |
202 | *s = '\0'; | |
203 | domname = user; | |
204 | user = s + 1; | |
205 | } | |
206 | /* match domname with linked list */ | |
207 | if (domname != nullptr && strlen(domname) > 0) { | |
208 | for (dom = firstdom; dom != nullptr; dom = dom->next) | |
209 | if (strcasecmp(dom->sname, domname) == 0) | |
210 | break; | |
211 | } else | |
212 | dom = firstdom; | |
213 | ||
214 | if (dom == nullptr) { | |
215 | SEND_ERR(""); | |
216 | continue; | |
217 | } | |
218 | if ((p = popen(shcmd, "w")) == nullptr) { | |
219 | SEND_ERR(""); | |
220 | continue; | |
221 | } | |
222 | (void) fprintf(p, "%s\n", dom->name); | |
223 | (void) fprintf(p, "%s\n", dom->passthrough); | |
224 | (void) fprintf(p, "%s\n", dom->nmbaddr); | |
225 | (void) fprintf(p, "%d\n", dom->nmbcast); | |
226 | (void) fprintf(p, "%s\n", dom->authshare); | |
227 | (void) fprintf(p, "%s\n", dom->authfile); | |
228 | (void) fprintf(p, "%s\n", user); | |
229 | /* the password can contain special characters */ | |
230 | print_esc(p, pass); | |
231 | (void) fputc('\n', p); | |
232 | (void) fflush(p); | |
233 | ||
234 | if (pclose(p) == 0) | |
235 | SEND_OK(""); | |
236 | else | |
237 | SEND_ERR(""); | |
238 | } /* while (1) */ | |
239 | ||
240 | return EXIT_SUCCESS; | |
241 | } | |
242 |