]>
Commit | Line | Data |
---|---|---|
f5691f9c | 1 | /* |
bde978a6 | 2 | * Copyright (C) 1996-2015 The Squid Software Foundation and contributors |
f5691f9c | 3 | * |
bbc27441 AJ |
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. | |
f5691f9c | 7 | */ |
8 | ||
bbc27441 AJ |
9 | /* DEBUG: section 29 Authenticator */ |
10 | ||
582c2af2 | 11 | #include "squid.h" |
2d2b0bb7 | 12 | #include "auth/Config.h" |
d8d76b36 | 13 | #include "auth/Gadgets.h" |
2d2b0bb7 | 14 | #include "auth/UserRequest.h" |
d4806c91 CT |
15 | #include "cache_cf.h" |
16 | #include "ConfigParser.h" | |
582c2af2 | 17 | #include "Debug.h" |
d4806c91 | 18 | #include "format/Format.h" |
582c2af2 | 19 | #include "globals.h" |
d4806c91 | 20 | #include "Store.h" |
3616c90c | 21 | #include "wordlist.h" |
f5691f9c | 22 | |
9f3d2b2e | 23 | Auth::ConfigVector Auth::TheConfig; |
5817ee13 AJ |
24 | |
25 | /** | |
9f3d2b2e AJ |
26 | * Get an User credentials object filled out for the given Proxy- or WWW-Authenticate header. |
27 | * Any decoding which needs to be done will be done. | |
28 | * | |
29 | * It may be a cached AuthUser or a new Unauthenticated object. | |
f5691f9c | 30 | * It may also be NULL reflecting that no user could be created. |
31 | */ | |
c7baff40 | 32 | Auth::UserRequest::Pointer |
d4806c91 | 33 | Auth::Config::CreateAuthUser(const char *proxy_auth, AccessLogEntry::Pointer &al) |
f5691f9c | 34 | { |
35 | assert(proxy_auth != NULL); | |
9f3d2b2e | 36 | debugs(29, 9, HERE << "header = '" << proxy_auth << "'"); |
f5691f9c | 37 | |
9f3d2b2e | 38 | Auth::Config *config = Find(proxy_auth); |
f5691f9c | 39 | |
40 | if (config == NULL || !config->active()) { | |
c6cf8dee | 41 | debugs(29, (shutting_down?3:DBG_IMPORTANT), (shutting_down?"":"WARNING: ") << |
8add28cd | 42 | "Unsupported or unconfigured/inactive proxy-auth scheme, '" << proxy_auth << "'"); |
f5691f9c | 43 | return NULL; |
44 | } | |
d4806c91 CT |
45 | static MemBuf rmb; |
46 | rmb.reset(); | |
47 | if (config->keyExtras) { | |
48 | // %credentials and %username, which normally included in | |
49 | // request_format, are - at this time, but that is OK | |
50 | // because user name is added to key explicitly, and we do | |
51 | // not want to store authenticated credentials at all. | |
52 | config->keyExtras->assemble(rmb, al, 0); | |
53 | } | |
f5691f9c | 54 | |
d4806c91 | 55 | return config->decode(proxy_auth, rmb.hasContent() ? rmb.content() : NULL); |
f5691f9c | 56 | } |
57 | ||
9f3d2b2e AJ |
58 | Auth::Config * |
59 | Auth::Config::Find(const char *proxy_auth) | |
f5691f9c | 60 | { |
9f3d2b2e | 61 | for (Auth::ConfigVector::iterator i = Auth::TheConfig.begin(); i != Auth::TheConfig.end(); ++i) |
f5691f9c | 62 | if (strncasecmp(proxy_auth, (*i)->type(), strlen((*i)->type())) == 0) |
63 | return *i; | |
64 | ||
65 | return NULL; | |
66 | } | |
62ee09ca | 67 | |
9f3d2b2e | 68 | /** Default behaviour is to expose nothing */ |
62ee09ca | 69 | void |
9f3d2b2e | 70 | Auth::Config::registerWithCacheManager(void) |
62ee09ca | 71 | {} |
d4806c91 CT |
72 | |
73 | void | |
ced8def3 | 74 | Auth::Config::parse(Auth::Config * scheme, int, char *param_str) |
d4806c91 | 75 | { |
3616c90c AJ |
76 | if (strcmp(param_str, "program") == 0) { |
77 | if (authenticateProgram) | |
78 | wordlistDestroy(&authenticateProgram); | |
79 | ||
80 | parse_wordlist(&authenticateProgram); | |
81 | ||
82 | requirePathnameExists("Authentication helper program", authenticateProgram->key); | |
83 | ||
84 | } else if (strcmp(param_str, "realm") == 0) { | |
ec980001 AJ |
85 | realm.clear(); |
86 | ||
87 | char *token = ConfigParser::NextQuotedOrToEol(); | |
88 | ||
fc3f1d5c | 89 | while (token && *token && xisspace(*token)) |
ec980001 AJ |
90 | ++token; |
91 | ||
92 | if (!token || !*token) { | |
93 | debugs(29, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: Missing auth_param " << scheme->type() << " realm"); | |
94 | self_destruct(); | |
95 | return; | |
96 | } | |
97 | ||
98 | realm = token; | |
99 | ||
100 | } else if (strcmp(param_str, "children") == 0) { | |
0309fc40 AJ |
101 | authenticateChildren.parseConfig(); |
102 | ||
103 | } else if (strcmp(param_str, "key_extras") == 0) { | |
d4806c91 CT |
104 | keyExtrasLine = ConfigParser::NextQuotedToken(); |
105 | Format::Format *nlf = new ::Format::Format(scheme->type()); | |
106 | if (!nlf->parse(keyExtrasLine.termedBuf())) { | |
107 | debugs(29, DBG_CRITICAL, "FATAL: Failed parsing key_extras formatting value"); | |
108 | self_destruct(); | |
109 | return; | |
110 | } | |
111 | if (keyExtras) | |
112 | delete keyExtras; | |
113 | ||
114 | keyExtras = nlf; | |
86c63190 | 115 | |
d4806c91 | 116 | if (char *t = strtok(NULL, w_space)) { |
86c63190 AJ |
117 | debugs(29, DBG_CRITICAL, "FATAL: Unexpected argument '" << t << "' after request_format specification"); |
118 | self_destruct(); | |
d4806c91 CT |
119 | } |
120 | } else { | |
121 | debugs(29, DBG_CRITICAL, "Unrecognised " << scheme->type() << " auth scheme parameter '" << param_str << "'"); | |
122 | } | |
123 | } | |
124 | ||
3616c90c AJ |
125 | bool |
126 | Auth::Config::dump(StoreEntry *entry, const char *name, Auth::Config *scheme) const | |
d4806c91 | 127 | { |
3616c90c AJ |
128 | if (!authenticateProgram) |
129 | return false; // not configured | |
130 | ||
131 | wordlist *list = authenticateProgram; | |
132 | storeAppendPrintf(entry, "%s %s", name, scheme->type()); | |
133 | while (list != NULL) { | |
134 | storeAppendPrintf(entry, " %s", list->key); | |
135 | list = list->next; | |
136 | } | |
137 | storeAppendPrintf(entry, "\n"); | |
138 | ||
ec980001 AJ |
139 | storeAppendPrintf(entry, "%s %s realm " SQUIDSBUFPH "\n", name, scheme->type(), SQUIDSBUFPRINT(realm)); |
140 | ||
0309fc40 AJ |
141 | storeAppendPrintf(entry, "%s %s children %d startup=%d idle=%d concurrency=%d\n", |
142 | name, scheme->type(), | |
143 | authenticateChildren.n_max, authenticateChildren.n_startup, | |
144 | authenticateChildren.n_idle, authenticateChildren.concurrency); | |
145 | ||
d4806c91 CT |
146 | if (keyExtrasLine.size() > 0) |
147 | storeAppendPrintf(entry, "%s %s key_extras \"%s\"\n", name, scheme->type(), keyExtrasLine.termedBuf()); | |
3616c90c AJ |
148 | |
149 | return true; | |
d4806c91 CT |
150 | } |
151 | ||
152 | void | |
153 | Auth::Config::done() | |
154 | { | |
155 | delete keyExtras; | |
86c63190 | 156 | keyExtras = NULL; |
d4806c91 CT |
157 | keyExtrasLine.clean(); |
158 | } | |
d8d76b36 FB |
159 | |
160 | Auth::User::Pointer | |
8c60f60f | 161 | Auth::Config::findUserInCache(const char *nameKey, Auth::Type authType) |
d8d76b36 FB |
162 | { |
163 | AuthUserHashPointer *usernamehash; | |
164 | debugs(29, 9, "Looking for user '" << nameKey << "'"); | |
165 | ||
166 | if (nameKey && (usernamehash = static_cast<AuthUserHashPointer *>(hash_lookup(proxy_auth_username_cache, nameKey)))) { | |
167 | while (usernamehash) { | |
8c60f60f | 168 | if ((usernamehash->user()->auth_type == authType) && |
d8d76b36 FB |
169 | !strcmp(nameKey, (char const *)usernamehash->key)) |
170 | return usernamehash->user(); | |
171 | ||
172 | usernamehash = static_cast<AuthUserHashPointer *>(usernamehash->next); | |
173 | } | |
174 | } | |
175 | ||
176 | return NULL; | |
177 | } | |
f53969cc | 178 |