SchemeConfig.cc
Go to the documentation of this file.
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 /* DEBUG: section 29 Authenticator */
10 
11 #include "squid.h"
12 #include "auth/Config.h"
13 #include "auth/forward.h"
14 #include "auth/Gadgets.h"
15 #include "auth/UserRequest.h"
16 #include "cache_cf.h"
17 #include "ConfigParser.h"
18 #include "debug/Stream.h"
19 #include "errorpage.h"
20 #include "format/Format.h"
21 #include "globals.h"
22 #include "Store.h"
23 #include "wordlist.h"
24 
34 {
35  assert(proxy_auth != nullptr);
36  debugs(29, 9, "header = '" << proxy_auth << "'");
37 
38  Auth::SchemeConfig *config = Find(proxy_auth);
39 
40  if (config == nullptr || !config->active()) {
41  debugs(29, (shutting_down?3:DBG_IMPORTANT), (shutting_down?"":"WARNING: ") <<
42  "Unsupported or unconfigured/inactive proxy-auth scheme, '" << proxy_auth << "'");
43  return nullptr;
44  }
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  }
54 
55  return config->decode(proxy_auth, al->request, rmb.hasContent() ? rmb.content() : nullptr);
56 }
57 
59 Auth::SchemeConfig::Find(const char *proxy_auth)
60 {
61  for (auto *scheme : Auth::TheConfig.schemes) {
62  if (strncasecmp(proxy_auth, scheme->type(), strlen(scheme->type())) == 0)
63  return scheme;
64  }
65 
66  return nullptr;
67 }
68 
70 Auth::SchemeConfig::GetParsed(const char *proxy_auth)
71 {
72  if (auto *cfg = Find(proxy_auth))
73  return cfg;
74  fatalf("auth_schemes: required authentication method '%s' is not configured", proxy_auth);
75  return nullptr;
76 }
77 
79 void
81 {}
82 
83 void
84 Auth::SchemeConfig::parse(Auth::SchemeConfig * scheme, int, char *param_str)
85 {
86  if (strcmp(param_str, "program") == 0) {
87  if (authenticateProgram)
88  wordlistDestroy(&authenticateProgram);
89 
90  parse_wordlist(&authenticateProgram);
91 
92  requirePathnameExists("Authentication helper program", authenticateProgram->key);
93 
94  } else if (strcmp(param_str, "realm") == 0) {
95  realm.clear();
96 
97  char *token = ConfigParser::NextQuotedOrToEol();
98 
99  while (token && *token && xisspace(*token))
100  ++token;
101 
102  if (!token || !*token) {
103  debugs(29, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: Missing auth_param " << scheme->type() << " realm");
104  self_destruct();
105  return;
106  }
107 
108  realm = token;
109 
110  } else if (strcmp(param_str, "children") == 0) {
111  authenticateChildren.parseConfig();
112 
113  } else if (strcmp(param_str, "key_extras") == 0) {
114  keyExtrasLine = ConfigParser::NextQuotedToken();
115  Format::Format *nlf = new ::Format::Format(scheme->type());
116  if (!nlf->parse(keyExtrasLine.termedBuf())) {
117  debugs(29, DBG_CRITICAL, "FATAL: Failed parsing key_extras formatting value");
118  self_destruct();
119  return;
120  }
121  if (keyExtras)
122  delete keyExtras;
123 
124  keyExtras = nlf;
125 
126  if (char *t = strtok(nullptr, w_space)) {
127  debugs(29, DBG_CRITICAL, "FATAL: Unexpected argument '" << t << "' after request_format specification");
128  self_destruct();
129  }
130  } else if (strcmp(param_str, "keep_alive") == 0) {
131  parse_onoff(&keep_alive);
132  } else if (strcmp(param_str, "utf8") == 0) {
133  parse_onoff(&utf8);
134  } else {
135  debugs(29, DBG_CRITICAL, "ERROR: Unrecognised " << scheme->type() << " auth scheme parameter '" << param_str << "'");
136  }
137 }
138 
139 bool
140 Auth::SchemeConfig::dump(StoreEntry *entry, const char *name, Auth::SchemeConfig *scheme) const
141 {
142  if (!authenticateProgram)
143  return false; // not configured
144 
145  const char *schemeType = scheme->type();
146 
147  wordlist *list = authenticateProgram;
148  storeAppendPrintf(entry, "%s %s", name, schemeType);
149  while (list != nullptr) {
150  storeAppendPrintf(entry, " %s", list->key);
151  list = list->next;
152  }
153  storeAppendPrintf(entry, "\n");
154 
155  storeAppendPrintf(entry, "%s %s realm " SQUIDSBUFPH "\n", name, schemeType, SQUIDSBUFPRINT(realm));
156 
157  storeAppendPrintf(entry, "%s %s children %d startup=%d idle=%d concurrency=%d\n",
158  name, schemeType,
159  authenticateChildren.n_max, authenticateChildren.n_startup,
160  authenticateChildren.n_idle, authenticateChildren.concurrency);
161 
162  if (keyExtrasLine.size() > 0) // default is none
163  storeAppendPrintf(entry, "%s %s key_extras \"%s\"\n", name, schemeType, keyExtrasLine.termedBuf());
164 
165  if (!keep_alive) // default is on
166  storeAppendPrintf(entry, "%s %s keep_alive off\n", name, schemeType);
167 
168  if (utf8) // default is off
169  storeAppendPrintf(entry, "%s %s utf8 on\n", name, schemeType);
170 
171  return true;
172 }
173 
174 void
176 {
177  delete keyExtras;
178  keyExtras = nullptr;
179  keyExtrasLine.clean();
180 }
181 
182 bool
184 {
185  String hdr;
186 
187  if (!request || !request->header.getList(Http::HdrType::ACCEPT_LANGUAGE, &hdr))
188  return false;
189 
190  char lang[256];
191  size_t pos = 0; // current parsing position in header string
192 
193  while (strHdrAcptLangGetItem(hdr, lang, 256, pos)) {
194 
195  /* wildcard uses the configured default language */
196  if (lang[0] == '*' && lang[1] == '\0')
197  return false;
198 
199  if ((strncmp(lang, "ru", 2) == 0 // Russian
200  || strncmp(lang, "uk", 2) == 0 // Ukrainian
201  || strncmp(lang, "be", 2) == 0 // Belorussian
202  || strncmp(lang, "bg", 2) == 0 // Bulgarian
203  || strncmp(lang, "sr", 2) == 0)) { // Serbian
204  if (lang[2] == '-') {
205  if (strcmp(lang + 3, "latn") == 0) // not Cyrillic
206  return false;
207  } else if (xisalpha(lang[2])) {
208  return false;
209  }
210 
211  return true;
212  }
213  }
214 
215  return false;
216 }
217 
virtual bool active() const =0
void wordlistDestroy(wordlist **list)
destroy a wordlist
Definition: wordlist.cc:16
#define DBG_CRITICAL
Definition: Stream.h:37
static char * NextQuotedToken()
HttpHeader header
Definition: Message.h:74
virtual UserRequest::Pointer decode(char const *proxy_auth, const HttpRequest *request, const char *requestRealm)=0
void storeAppendPrintf(StoreEntry *e, const char *fmt,...)
Definition: store.cc:855
bool hasContent() const
Definition: MemBuf.h:54
bool isCP1251EncodingAllowed(const HttpRequest *request)
String getList(Http::HdrType id) const
Definition: HttpHeader.cc:788
Auth::Config TheConfig
Definition: Config.cc:15
bool parse(const char *def)
Definition: Format.cc:66
#define w_space
void self_destruct(void)
Definition: cache_cf.cc:276
void requirePathnameExists(const char *name, const char *path)
Definition: cache_cf.cc:3926
static SchemeConfig * Find(const char *proxy_auth)
Definition: SchemeConfig.cc:59
HttpRequest * request
virtual void parse(SchemeConfig *, int, char *)
Definition: SchemeConfig.cc:84
#define xisalpha(x)
Definition: xis.h:21
#define SQUIDSBUFPRINT(s)
Definition: SBuf.h:32
#define DBG_PARSE_NOTE(x)
Definition: Stream.h:42
@ ACCEPT_LANGUAGE
bool strHdrAcptLangGetItem(const String &hdr, char *lang, int langLen, size_t &pos)
Definition: errorpage.cc:472
Definition: MemBuf.h:23
virtual const char * type() const =0
static SchemeConfig * GetParsed(const char *proxy_auth)
Definition: SchemeConfig.cc:70
#define assert(EX)
Definition: assert.h:17
void fatalf(const char *fmt,...)
Definition: fatal.cc:68
Format
whether Action report uses valid YAML or unspecified/legacy formatting
Format::Format * keyExtras
The compiled request format.
Definition: SchemeConfig.h:131
wordlist * next
Definition: wordlist.h:60
char * key
Definition: wordlist.h:59
static char * NextQuotedOrToEol()
static UserRequest::Pointer CreateAuthUser(const char *proxy_auth, AccessLogEntry::Pointer &al)
Definition: SchemeConfig.cc:33
char * content()
start of the added data
Definition: MemBuf.h:41
#define DBG_IMPORTANT
Definition: Stream.h:38
void reset()
Definition: MemBuf.cc:129
void assemble(MemBuf &mb, const AccessLogEntryPointer &al, int logSequenceNumber) const
assemble the state information into a formatted line.
Definition: Format.cc:377
void parse_onoff(int *var)
Definition: cache_cf.cc:2580
virtual void done()
int shutting_down
virtual bool dump(StoreEntry *, const char *, SchemeConfig *) const
virtual void registerWithCacheManager(void)
Definition: SchemeConfig.cc:80
#define xisspace(x)
Definition: xis.h:15
void parse_wordlist(wordlist **list)
Definition: cache_cf.cc:3134
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:192
#define SQUIDSBUFPH
Definition: SBuf.h:31

 

Introduction

Documentation

Support

Miscellaneous