MBDyn-1.7.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups
auth.cc
Go to the documentation of this file.
1 /* $Header: /var/cvs/mbdyn/mbdyn/mbdyn-1.0/mbdyn/base/auth.cc,v 1.41 2017/01/12 14:46:08 masarati Exp $ */
2 /*
3  * MBDyn (C) is a multibody analysis code.
4  * http://www.mbdyn.org
5  *
6  * Copyright (C) 1996-2017
7  *
8  * Pierangelo Masarati <masarati@aero.polimi.it>
9  * Paolo Mantegazza <mantegazza@aero.polimi.it>
10  *
11  * Dipartimento di Ingegneria Aerospaziale - Politecnico di Milano
12  * via La Masa, 34 - 20156 Milano, Italy
13  * http://www.aero.polimi.it
14  *
15  * Changing this copyright notice is forbidden.
16  *
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation (version 2 of the License).
20  *
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30  */
31 
32 #include "mbconfig.h" // This goes first in every *.c,*.cc file
33 
34 #include <unistd.h>
35 #ifdef HAVE_PWD_H
36 #include <pwd.h>
37 #endif // HAVE_PWD_H
38 
39 #include "dataman.h"
40 #include "auth.h"
41 #include "crypt.h"
42 
43 /* NoAuth - begin */
44 
45 /* from sockdrv.c */
46 extern int get_auth_token(FILE *fd, char *user, char *cred, char **nextline);
47 
49 NoAuth::Auth(const char * /* user */ , const char * /* cred */ ) const
50 {
51  return AuthMethod::AUTH_OK;
52 }
53 
55 NoAuth::Auth(int /* sock */ ) const
56 {
57  return AuthMethod::AUTH_OK;
58 }
59 
60 /* NoAuth - end */
61 
62 
63 /* PasswordAuth - begin */
64 
65 #ifdef HAVE_CRYPT
66 
67 PasswordAuth::PasswordAuth(const char *u, const char *c, const char *salt_format)
68 {
69  ASSERT(u != NULL);
70  ASSERT(c != NULL);
71 
72  strncpy(User, u, sizeof(User));
73  User[STRLENOF(User)] = '\0';
74 
75  char *tmp = 0;
76  if (strncmp(c, "{CRYPT}", STRLENOF("{CRYPT}")) == 0) {
77  tmp = &c[STRLENOF("{CRYPT}")];
78 
79  if (strlen(tmp) >= sizeof(Cred)) {
80  silent_cerr("unable to handle credentials (too long)"
81  << std::endl);
83  }
84 
85  } else {
86  char salt[33];
87  tmp = crypt(c, mbdyn_make_salt(salt, sizeof(salt), salt_format));
88  if (tmp == NULL) {
89  silent_cerr("crypt() failed" << std::endl);
91  }
92  }
93 
94  strncpy(Cred, tmp, sizeof(Cred));
95  Cred[STRLENOF(Cred)] = '\0';
96 }
97 
99 PasswordAuth::Auth(const char *user, const char *cred) const
100 {
101  if (user == NULL || cred == NULL) {
102  return AuthMethod::AUTH_ERR;
103  }
104 
105  char *tmp = crypt(cred, Cred);
106  if (tmp == NULL) {
108  }
109 
110  if (strcmp(User, user) == 0 && strcmp(Cred, tmp) == 0) {
111  return AuthMethod::AUTH_OK;
112  }
113 
114  return AuthMethod::AUTH_FAIL;
115 }
116 
118 PasswordAuth::Auth(int sock) const
119 {
121 }
122 
123 #endif /* HAVE_CRYPT */
124 
125 /* PasswordAuth - end */
126 
127 
128 /* PAM_Auth - begin */
129 
130 #ifdef USE_PAM
131 
132 extern "C" {
133 #include <security/pam_appl.h>
134 #ifdef HAVE_PAM_MISC_H
135 #include <pam_misc.h>
136 #elif HAVE_SECURITY_PAM_MISC_H
137 #include <security/pam_misc.h>
138 #endif /* HAVE_SECURITY_PAM_MISC_H */
139 #include <string.h>
140 }
141 
142 #define INPUTSIZE PAM_MAX_MSG_SIZE /* maximum length of input+1 */
143 #define CONV_ECHO_ON 1 /* types of echo state */
144 #define CONV_ECHO_OFF 0
145 
146 static void
147 pam_misc_conv_delete_binary(void **delete_me)
148 {
149  if (delete_me && *delete_me) {
150  unsigned char *packet = *(unsigned char **)delete_me;
151  int length;
152 
153  length = 4+(packet[0]<<24)+(packet[1]<<16)+(packet[2]<<8)+packet[3];
154  memset(packet, 0, length);
155  free(packet);
156  *delete_me = packet = NULL;
157  }
158 }
159 
160 int (*mb_pam_bh_fn)(const void *send, void **receive) = NULL;
161 void (*mb_pam_bh_free)(void **packet_p) = pam_misc_conv_delete_binary;
162 
163 /*
164  * Uso una funzione di conversazione che si limita a restituire il valore
165  * di credenziali passato in appdata_ptr (cast a void*)
166  */
167 int
168 mbdyn_conv(int num_msg, const struct pam_message **msgm,
169  struct pam_response **response, void *appdata_ptr)
170 {
171  int count = 0;
172  struct pam_response *reply;
173 
174  if (num_msg <= 0) {
175  return PAM_CONV_ERR;
176  }
177 
178  reply = (struct pam_response *) calloc(num_msg, sizeof(struct pam_response));
179  if (reply == NULL) {
180  return PAM_CONV_ERR;
181  }
182 
183  for (count = 0; count < num_msg; ++count) {
184  char *string = NULL;
185 
186  switch (msgm[count]->msg_style) {
187  case PAM_PROMPT_ECHO_OFF:
188  case PAM_PROMPT_ECHO_ON:
189  string = (char *)x_strdup((char *)appdata_ptr);
190  if (string == NULL) {
191  goto failed_conversation;
192  }
193  break;
194 
195  case PAM_ERROR_MSG:
196  if (fprintf(stderr, "%s\n", msgm[count]->msg) < 0) {
197  goto failed_conversation;
198  }
199  break;
200 
201  case PAM_TEXT_INFO:
202  if (::fSilent < 2) {
203  if (fprintf(stdout, "%s\n", msgm[count]->msg) < 0) {
204  goto failed_conversation;
205  }
206  }
207  break;
208 
209  case PAM_BINARY_PROMPT: {
210  void *pack_out = NULL;
211  const void *pack_in = msgm[count]->msg;
212 
213  if (!mb_pam_bh_fn
214  || mb_pam_bh_fn(pack_in, &pack_out) != PAM_SUCCESS
215  || pack_out == NULL) {
216  goto failed_conversation;
217  }
218  string = (char *) pack_out;
219  pack_out = NULL;
220  break;
221  }
222 #if 0 /* non-standard message styles */
223  case PAM_BINARY_MSG: {
224  const void *pack_in = msgm[count]->msg;
225  if (!pam_binary_handler_fn
226  || pam_binary_handler_fn(pack_in, NULL) != PAM_SUCCESS) {
227  goto failed_conversation;
228  }
229  break;
230  }
231 #endif /* non-standard message styles */
232 
233  default:
234  fprintf(stderr, "erroneous conversation (%d)\n",
235  msgm[count]->msg_style);
236  goto failed_conversation;
237  }
238 
239  if (string) { /* must add to reply array */
240  /* add string to list of responses */
241  reply[count].resp_retcode = 0;
242  reply[count].resp = string;
243  string = NULL;
244  }
245  }
246 
247  /* New (0.59+) behavior is to always have a reply - this is
248  * compatable with the X/Open (March 1997) spec. */
249  *response = reply;
250  reply = NULL;
251 
252  return PAM_SUCCESS;
253 
254 failed_conversation:;
255  if (reply) {
256  for (count = 0; count < num_msg; ++count) {
257  if (reply[count].resp == NULL) {
258  continue;
259  }
260 
261  switch (msgm[count]->msg_style) {
262  case PAM_PROMPT_ECHO_ON:
263  case PAM_PROMPT_ECHO_OFF:
264  _pam_overwrite(reply[count].resp);
265  free(reply[count].resp);
266  break;
267 
268  case PAM_BINARY_PROMPT:
269  mb_pam_bh_free((void **) &reply[count].resp);
270  break;
271 
272  case PAM_ERROR_MSG:
273  case PAM_TEXT_INFO:
274 #if 0 /* non-standard message style */
275  case PAM_BINARY_MSG:
276 #endif /* non-standard message style */
277  /* should not actually be able to get here ... */
278  free(reply[count].resp);
279  }
280 
281  reply[count].resp = NULL;
282  }
283 
284  /* forget reply too */
285  free(reply);
286  reply = NULL;
287  }
288 
289  return PAM_CONV_ERR;
290 }
291 
292 PAM_Auth::PAM_Auth(const char *u)
293 : User(NULL)
294 {
295  if (u == NULL) {
296  struct passwd* pw = getpwuid(getuid());
297 
298  if (pw == NULL) {
299  silent_cerr("PAM_Auth: cannot determine the effective user!" << std::endl);
301  }
302 
303  u = pw->pw_name;
304  }
305 
306  SAFESTRDUP(User, u);
307 
308  struct pam_conv conv;
309  conv.conv = mbdyn_conv;
310  conv.appdata_ptr = NULL;
311 
312  pam_handle_t *pamh = NULL;
313  int retval = pam_start("mbdyn", User, &conv, &pamh);
314 
315  if (retval != PAM_SUCCESS) {
316  silent_cerr("PAM_Auth: user \"" << User
317  << "\" cannot be authenticated " << std::endl);
318 
319  if (pam_end(pamh, retval) != PAM_SUCCESS) {
320  silent_cerr("PAM_Auth: unable to release PAM authenticator" << std::endl);
321  }
322 
324  }
325 
326  if (pam_end(pamh, retval) != PAM_SUCCESS) {
327  silent_cerr("PAM_Auth: unable to release PAM authenticator" << std::endl);
328  }
329 }
330 
332 PAM_Auth::Auth(const char *user, const char *cred) const
333 {
334  pam_handle_t *pamh = NULL;
335  int retval;
336 
338 
339  if (user == NULL || cred == NULL) {
340  return AuthMethod::AUTH_ERR;
341  }
342 
343  if (strcmp(User, user) != 0) {
344  silent_cerr("PAM_Auth::Auth: user \"" << user
345  << "\" cannot be authenticated " << std::endl);
346  return AuthMethod::AUTH_ERR;
347  }
348 
349  struct pam_conv conv;
350  conv.conv = mbdyn_conv;
351  conv.appdata_ptr = (void*)cred;
352  retval = pam_start("mbdyn", User, &conv, &pamh);
353  if (retval == PAM_SUCCESS) {
354  retval = pam_authenticate(pamh, 0);
355  if (retval == PAM_SUCCESS) {
357  } else {
359  }
360  } else {
362  }
363 
364  if (pam_end(pamh, retval) != PAM_SUCCESS) {
365  silent_cerr("PAM_Auth::Auth: unable to release PAM authenticator" << std::endl);
366  }
367 
368  return r;
369 }
370 
372 PAM_Auth::Auth(int sock) const
373 {
375 }
376 
377 #endif /* USE_PAM */
378 
379 /* PAM_Auth - end */
380 
381 #ifdef HAVE_SASL2
382 
383 #if defined(HAVE_SASL_SASL_H)
384 #include <sasl/sasl.h>
385 #elif defined(HAVE_SASL_H)
386 #include <sasl.h>
387 #endif /* HAVE_SASL_SASL_H || HAVE_SASL_H */
388 #include "mbsasl.h"
389 
390 int
391 mbdyn_sasl_log(void *context, int level, const char *message)
392 {
393  switch (level) {
394  case 0:
395  case 1:
396  std::cerr << "[mbdyn " << level << "] " << message << std::endl;
397  break;
398 
399  case 2:
400  silent_cerr("[mbdyn " << level << "] " << message << std::endl);
401  break;
402 
403  case 3:
404  std::cout << "[mbdyn " << level << "] " << message << std::endl;
405  break;
406 
407  default:
408  silent_cout("[mbdyn " << level << "] " << message << std::endl);
409  break;
410  }
411 
412  return 0;
413 }
414 
415 SASL2_Auth::SASL2_Auth(const mbdyn_sasl_t *ms)
416 : mbdyn_sasl(*ms)
417 {
418  /* server operations */
419  log_server_f = mbdyn_sasl_log;
420 
421  if (mbdyn_sasl_init(&mbdyn_sasl) != SASL_OK) {
423  }
424 }
425 
427 SASL2_Auth::Auth(const char *user, const char *cred) const
428 {
430 }
431 
433 SASL2_Auth::Auth(int sock) const
434 {
435  switch (mbdyn_sasl_auth(sock, NULL, &mbdyn_sasl)) {
436  case SASL_OK:
437  return AuthMethod::AUTH_OK;
438 
439  case SASL_FAIL:
440  return AuthMethod::AUTH_FAIL;
441 
442  default:
443  return AuthMethod::AUTH_ERR;
444  }
445 }
446 
447 #endif /* HAVE_SASL2 */
448 
449 
450 AuthMethod*
451 ReadAuthMethod(const DataManager* /* pDM */ , MBDynParser& HP)
452 {
453  AuthMethod* pAuth = NULL;
454 
455  const char* sKeyWords[] = {
456  "noauth",
457  "password",
458  "pwdb",
459  "pam",
460  "sasl",
461  NULL
462  };
463 
464  enum KeyWords {
465  UNKNOWN = -1,
466 
467  NOAUTH = 0,
468  PASSWORD,
469  PWDB,
470  PAM,
471  SASL,
472 
474  };
475 
476  /* tabella delle parole chiave */
477  KeyTable K(HP, sKeyWords);
478 
479  /* lettura del tipo di drive */
480  KeyWords CurrKeyWord = KeyWords(HP.GetWord());
481 
482  switch (CurrKeyWord) {
483  /* auth is always successful */
484  case NOAUTH:
485  SAFENEW(pAuth, NoAuth);
486  break;
487 
488  /* auth is based on user id and password */
489  case PASSWORD: {
490 #ifdef HAVE_CRYPT
491  if (!HP.IsKeyWord("user")) {
492  silent_cerr("ReadAuthMethod: user expected at line "
493  << HP.GetLineData() << std::endl);
495  }
496 
497  const char* tmp = HP.GetStringWithDelims();
498  if (strlen(tmp) == 0) {
499  silent_cerr("ReadAuthMethod: Need a legal user id at line "
500  << HP.GetLineData() << std::endl);
502  }
503 
504  std::string user(tmp);
505 
506  if (!HP.IsKeyWord("credentials")) {
507  silent_cerr("ReadAuthMethod: credentials expected at line "
508  << HP.GetLineData() << std::endl);
510  }
511 
512  if (HP.IsKeyWord("prompt")) {
513  tmp = getpass("password: ");
514  } else {
515  tmp = HP.GetStringWithDelims();
516  }
517 
518  if (tmp[0] == '\0') {
519  silent_cout("ReadAuthMethod: null credentials at line "
520  << HP.GetLineData() << std::endl);
521  }
522 
523  std::string cred(tmp);
524  memset((char *)tmp, '\0', strlen(tmp));
525 
526  std::string salt_format;
527  if (HP.IsKeyWord("salt" "format")) {
528  tmp = HP.GetStringWithDelims();
529  salt_format = tmp;
530  }
531 
533  PasswordAuth,
534  PasswordAuth(user.c_str(), cred.c_str(), salt_format.c_str()));
535  memset(cred.c_str(), '\0', cred.size());
536 
537  break;
538 #else /* !HAVE_CRYPT */
539  silent_cerr("ReadAuthMethod: line " << HP.GetLineData()
540  << ": no working crypt(3)" << std::endl);
542 #endif /* !HAVE_CRYPT */
543  }
544 
545  case PAM: {
546 #ifdef USE_PAM
547  char* user = NULL;
548  if (HP.IsKeyWord("user")) {
549  const char *tmp = HP.GetStringWithDelims();
550  if (strlen(tmp) == 0) {
551  silent_cerr("ReadAuthMethod: Need a legal user id at line "
552  << HP.GetLineData() << std::endl);
554  }
555 
556  SAFESTRDUP(user, tmp);
557  }
558 
559  SAFENEWWITHCONSTRUCTOR(pAuth, PAM_Auth, PAM_Auth(user));
560  break;
561 #else /* !USE_PAM */
562  silent_cerr("ReadAuthMethod: line " << HP.GetLineData()
563  << ": no PAM support" << std::endl);
565 #endif /* !USE_PAM */
566  }
567 
568  case SASL: {
569 #ifdef HAVE_SASL2
570  mbdyn_sasl_t mbdyn_sasl = MBDYN_SASL_INIT;
571  mbdyn_sasl.use_sasl = MBDYN_SASL_SERVER;
572 
573  if (HP.IsKeyWord("mechanism") || HP.IsKeyWord("mech")) {
574  const char *s = HP.GetStringWithDelims();
575  if (s != NULL) {
576  SAFESTRDUP(mbdyn_sasl.sasl_mech, s);
577  } else {
578  silent_cerr("ReadAuthMethod: unable to get SASL mech at line "
579  << HP.GetLineData() << std::endl);
580  }
581  }
582 
583  SAFENEWWITHCONSTRUCTOR(pAuth, SASL2_Auth, SASL2_Auth(&mbdyn_sasl));
584  break;
585 #else /* !HAVE_SASL2 */
586  silent_cerr("ReadAuthMethod: line " << HP.GetLineData()
587  << ": no SASL2 support" << std::endl);
589 #endif /* !HAVE_SASL2 */
590  }
591 
592  case PWDB:
593  silent_cerr("ReadAuthMethod: PWDB not implemented yet" << std::endl);
594 
595  default:
597  }
598 
599  return pAuth;
600 }
601 
AuthMethod::AuthRes Auth(const char *, const char *) const
Definition: auth.cc:49
#define MBDYN_EXCEPT_ARGS
Definition: except.h:63
int fSilent
Definition: myassert.cc:58
int get_auth_token(FILE *fd, char *user, char *cred, char **nextline)
AuthRes
Definition: auth.h:40
Definition: auth.h:58
#define SAFENEW(pnt, item)
Definition: mynewmem.h:695
virtual bool IsKeyWord(const char *sKeyWord)
Definition: parser.cc:910
octave_value_list retval
static int count
Definition: modules.cc:41
virtual const char * GetStringWithDelims(enum Delims Del=DEFAULTDELIM, bool escape=true)
Definition: parser.cc:1228
#define ASSERT(expression)
Definition: colamd.c:977
KeyWords
Definition: dataman4.cc:94
#define SAFENEWWITHCONSTRUCTOR(pnt, item, constructor)
Definition: mynewmem.h:698
static std::stack< cleanup * > c
Definition: cleanup.cc:59
#define STRLENOF(s)
Definition: mbdyn.h:166
char * mbdyn_make_salt(char *salt, size_t saltlen, const char *salt_format)
Definition: crypt.cc:40
struct mbrtai_msg_t msg
virtual int GetWord(void)
Definition: parser.cc:1083
#define SAFESTRDUP(pnt, src)
Definition: mynewmem.h:707
AuthMethod * ReadAuthMethod(const DataManager *, MBDynParser &HP)
Definition: auth.cc:451
virtual HighParser::ErrOut GetLineData(void) const
Definition: parsinc.cc:697