irods  4.2.8
About: iRODS (the integrated Rule Oriented Data System) is a distributed data-management system for creating data grids, digital libraries, persistent archives, and real-time data systems.
  Fossies Dox: irods-4.2.8.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

clientLogin.cpp
Go to the documentation of this file.
1 
3 /* clientLogin.c - client login
4  *
5  * Perform a series of calls to complete a client login; to
6  * authenticate.
7  */
8 
9 // =-=-=-=-=-=-=-
10 // irods includes
11 #include "rcGlobalExtern.h"
12 #include "rodsClient.h"
13 #include "sslSockComm.h"
14 
15 // =-=-=-=-=-=-=-
16 #include "irods_auth_object.hpp"
17 #include "irods_auth_factory.hpp"
18 #include "irods_auth_plugin.hpp"
19 #include "irods_auth_manager.hpp"
20 #include "irods_auth_constants.hpp"
23 #include "authPluginRequest.h"
26 #include "checksum.hpp"
27 #include "termiosUtil.hpp"
28 
29 
32 
33 
34 
35 #include <openssl/md5.h>
36 #include <boost/filesystem/operations.hpp>
37 #include <boost/filesystem/convenience.hpp>
38 
39 #include <errno.h>
40 #include <termios.h>
41 
43 
46 }
47 
48 void setSessionSignatureClientside( char* _sig ) {
49  snprintf(
51  200,
52  "%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",
53  ( unsigned char )_sig[0],
54  ( unsigned char )_sig[1],
55  ( unsigned char )_sig[2],
56  ( unsigned char )_sig[3],
57  ( unsigned char )_sig[4],
58  ( unsigned char )_sig[5],
59  ( unsigned char )_sig[6],
60  ( unsigned char )_sig[7],
61  ( unsigned char )_sig[8],
62  ( unsigned char )_sig[9],
63  ( unsigned char )_sig[10],
64  ( unsigned char )_sig[11],
65  ( unsigned char )_sig[12],
66  ( unsigned char )_sig[13],
67  ( unsigned char )_sig[14],
68  ( unsigned char )_sig[15] );
69 
70 } // setSessionSignatureClientside
71 
72 
73 
74 int printError( rcComm_t *Conn, int status, char *routineName ) {
75  rError_t *Err;
76  rErrMsg_t *ErrMsg;
77  int i, len;
78  if ( Conn ) {
79  if ( Conn->rError ) {
80  Err = Conn->rError;
81  len = Err->len;
82  for ( i = 0; i < len; i++ ) {
83  ErrMsg = Err->errMsg[i];
84  fprintf( stderr, "Level %d: %s\n", i, ErrMsg->msg );
85  }
86  }
87  }
88  char *mySubName = NULL;
89  const char *myName = rodsErrorName( status, &mySubName );
90  fprintf( stderr, "%s failed with error %d %s %s\n", routineName,
91  status, myName, mySubName );
92  free( mySubName );
93 
94  return 0;
95 }
96 
98  char* password,
99  int ttl ) {
100  using namespace boost::filesystem;
101  int status = 0;
102  pamAuthRequestInp_t pamAuthReqInp;
103  pamAuthRequestOut_t *pamAuthReqOut = NULL;
104  int len = 0;
105  char myPassword[MAX_PASSWORD_LEN + 2];
106  char userName[NAME_LEN * 2];
107  strncpy( userName, Conn->proxyUser.userName, NAME_LEN );
108  if ( password[0] != '\0' ) {
109  strncpy( myPassword, password, sizeof( myPassword ) );
110  }
111  else {
112  irods::termiosUtil tiosutl(STDIN_FILENO);
113  if ( !tiosutl.echoOff() )
114  {
115  printf( "WARNING: Error %d disabling echo mode. Password will be displayed in plaintext.\n", tiosutl.getError() );
116  }
117 
118  printf( "Enter your current PAM (system) password:" );
119 
120  const char *fgets_return = fgets( myPassword, sizeof( myPassword ), stdin );
121  if (fgets_return != myPassword || strlen(myPassword) < 2) {
122  // We're here because we either got an error or end-of-file.
123  myPassword[0] = '\0';
124  }
125 
126  printf( "\n" );
127  if( tiosutl.getValid() && !tiosutl.echoOn() )
128  {
129  printf( "Error reinstating echo mode.\n" );
130  }
131  }
132  len = strlen( myPassword );
133  if ( len > 0 && myPassword[len - 1] == '\n' ) {
134  myPassword[len - 1] = '\0'; /* remove trailing \n */
135  }
136 
137  /* since PAM requires a plain text password to be sent
138  to the server, ask the server to encrypt the current
139  communication socket. */
140  status = sslStart( Conn );
141  if ( status ) {
142  printError( Conn, status, "sslStart" );
143  return status;
144  }
145 
146  memset( &pamAuthReqInp, 0, sizeof( pamAuthReqInp ) );
147  pamAuthReqInp.pamPassword = myPassword;
148  pamAuthReqInp.pamUser = userName;
149  pamAuthReqInp.timeToLive = ttl;
150  status = rcPamAuthRequest( Conn, &pamAuthReqInp, &pamAuthReqOut );
151  if ( status ) {
152  printError( Conn, status, "rcPamAuthRequest" );
153  sslEnd( Conn );
154  return status;
155  }
156  memset( myPassword, 0, sizeof( myPassword ) );
157  rodsLog( LOG_NOTICE, "iRODS password set up for iCommand use: %s\n",
158  pamAuthReqOut->irodsPamPassword );
159 
160  /* can turn off SSL now. Have to request the server to do so.
161  Will also ignore any error returns, as future socket ops
162  are probably unaffected. */
163  sslEnd( Conn );
164 
165  status = obfSavePw( 0, 0, 0, pamAuthReqOut->irodsPamPassword );
166  return status;
167 
168 }
169 
170 /*
171  Make a short-lived password.
172  TTL is Time-to-live, in hours, typically in the few days range.
173  */
174 int clientLoginTTL( rcComm_t *Conn, int ttl ) {
175 
176  char userPassword[MAX_PASSWORD_LEN + 10];
177  if ( int status = obfGetPw( userPassword ) ) {
178  memset( userPassword, 0, sizeof( userPassword ) );
179  return status;
180  }
181 
182  getLimitedPasswordInp_t getLimitedPasswordInp;
183  getLimitedPasswordInp.ttl = ttl;
184  getLimitedPasswordInp.unused1 = "";
185 
186  getLimitedPasswordOut_t *getLimitedPasswordOut;
187  if ( int status = rcGetLimitedPassword( Conn,
188  &getLimitedPasswordInp,
189  &getLimitedPasswordOut ) ) {
190  printError( Conn, status, "rcGetLimitedPassword" );
191  memset( userPassword, 0, sizeof( userPassword ) );
192  return status;
193  }
194 
195  /* calcuate the limited password, which is a hash of the user's main pw and
196  the returned stringToHashWith. */
197  char hashBuf[101];
198  memset( hashBuf, 0, sizeof( hashBuf ) );
199  strncpy( hashBuf, getLimitedPasswordOut->stringToHashWith, 100 );
200  strncat( hashBuf, userPassword, 100 );
201  memset( userPassword, 0, sizeof( userPassword ) );
202 
203  unsigned char digest[100];
206  ( unsigned char* )hashBuf,
207  100,
208  digest );
209  memset( hashBuf, 0, sizeof( hashBuf ) );
210 
211  char limitedPw[100];
212  hashToStr( digest, limitedPw );
213 
214  return obfSavePw( 0, 0, 0, limitedPw );
215 }
216 
217 
223  rcComm_t* _comm,
224  const char* _context,
225  const char* _scheme_override ) {
226  // =-=-=-=-=-=-=-
227  // check out conn pointer
228  if ( !_comm ) {
230  }
231 
232  if ( 1 == _comm->loggedIn ) {
233  return 0;
234  }
235 
236  // =-=-=-=-=-=-=-
237  // get the rods environment so we can determine the
238  // flavor of authentication desired by the user -
239  // check the environment variable first then the rods
240  // env if that was null
241  std::string auth_scheme = irods::AUTH_NATIVE_SCHEME;
242  if ( ProcessType == CLIENT_PT ) {
243  // =-=-=-=-=-=-=-
244  // the caller may want to override the env var
245  // or irods env file configuration ( PAM )
246  if ( _scheme_override && strlen( _scheme_override ) > 0 ) {
247  auth_scheme = _scheme_override;
248  }
249  else {
250  // =-=-=-=-=-=-=-
251  // check the environment variable first
252  char* auth_env_var = getenv( irods::to_env( irods::CFG_IRODS_AUTHENTICATION_SCHEME_KW ).c_str() );
253  if ( !auth_env_var ) {
254  rodsEnv rods_env;
255  if ( getRodsEnv( &rods_env ) >= 0 ) {
256  if ( strlen( rods_env.rodsAuthScheme ) > 0 ) {
257  auth_scheme = rods_env.rodsAuthScheme;
258  }
259  }
260  }
261  else {
262  auth_scheme = auth_env_var;
263  }
264 
265  // =-=-=-=-=-=-=-
266  // ensure scheme is lower case for comparison
267  std::string lower_scheme = auth_scheme;
268  std::transform( auth_scheme.begin(), auth_scheme.end(), auth_scheme.begin(), ::tolower );
269 
270  // =-=-=-=-=-=-=-
271  // filter out the pam auth as it is an extra special
272  // case and only sent in as an override.
273  // everyone other scheme behaves as normal
274  if ( irods::AUTH_PAM_SCHEME == auth_scheme ) {
275  auth_scheme = irods::AUTH_NATIVE_SCHEME;
276  }
277  } // if _scheme_override
278  } // if client side auth
279 
280  // =-=-=-=-=-=-=-
281  // construct an auth object given the scheme
282  irods::auth_object_ptr auth_obj;
283  irods::error ret = irods::auth_factory( auth_scheme, _comm->rError, auth_obj );
284  if ( !ret.ok() ) {
285  irods::log( PASS( ret ) );
286  return ret.code();
287  }
288 
289  // =-=-=-=-=-=-=-
290  // resolve an auth plugin given the auth object
291  irods::plugin_ptr ptr;
292  ret = auth_obj->resolve( irods::AUTH_INTERFACE, ptr );
293  if ( !ret.ok() ) {
294  irods::log( PASS( ret ) );
295  return ret.code();
296  }
297  irods::auth_ptr auth_plugin = boost::dynamic_pointer_cast< irods::auth >( ptr );
298 
299  // =-=-=-=-=-=-=-
300  // call client side init
301  ret = auth_plugin->call <rcComm_t*, const char* > ( NULL, irods::AUTH_CLIENT_START, auth_obj, _comm, _context );
302  if ( !ret.ok() ) {
303  irods::log( PASS( ret ) );
304  return ret.code();
305  }
306 
307  // =-=-=-=-=-=-=-
308  // send an authentication request to the server
309  ret = auth_plugin->call <rcComm_t* > ( NULL, irods::AUTH_CLIENT_AUTH_REQUEST, auth_obj, _comm );
310  if ( !ret.ok() ) {
311  printError(
312  _comm,
313  ret.code(),
314  ( char* )ret.result().c_str() );
315  return ret.code();
316  }
317 
318  // =-=-=-=-=-=-=-
319  // establish auth context client side
320  ret = auth_plugin->call( NULL, irods::AUTH_ESTABLISH_CONTEXT, auth_obj );
321  if ( !ret.ok() ) {
322  irods::log( PASS( ret ) );
323  return ret.code();
324  }
325 
326  // =-=-=-=-=-=-=-
327  // send the auth response to the agent
328  ret = auth_plugin->call <rcComm_t* > ( NULL, irods::AUTH_CLIENT_AUTH_RESPONSE, auth_obj, _comm );
329  if ( !ret.ok() ) {
330  printError(
331  _comm,
332  ret.code(),
333  ( char* )ret.result().c_str() );
334  return ret.code();
335  }
336 
337  // =-=-=-=-=-=-=-
338  // set the flag stating we are logged in
339  _comm->loggedIn = 1;
340 
341  // =-=-=-=-=-=-=-
342  // win!
343  return 0;
344 
345 } // clientLogin
346 
347 int
348 clientLoginWithPassword( rcComm_t *Conn, char* password ) {
349  int status, len, i = 0;
350  authRequestOut_t *authReqOut = NULL;
351  authResponseInp_t authRespIn;
352  char md5Buf[CHALLENGE_LEN + MAX_PASSWORD_LEN + 2];
353  char digest[RESPONSE_LEN + 2];
354  char userNameAndZone[NAME_LEN * 2 + 1];
355  MD5_CTX context;
356  if ( !password ) {
357  printError( Conn, -1, "null password pointer" );
358  return -1;
359  }
360 
361  if ( Conn->loggedIn == 1 ) {
362  /* already logged in */
363  return 0;
364  }
365  status = rcAuthRequest( Conn, &authReqOut );
366  if ( status || NULL == authReqOut ) { // JMC cppcheck - nullptr
367  printError( Conn, status, "rcAuthRequest" );
368  return status;
369  }
370 
371  memset( md5Buf, 0, sizeof( md5Buf ) );
372  strncpy( md5Buf, authReqOut->challenge, CHALLENGE_LEN );
374 
375 
376  len = strlen( password );
377  sprintf( md5Buf + CHALLENGE_LEN, "%s", password );
378  md5Buf[CHALLENGE_LEN + len] = '\0'; /* remove trailing \n */
379 
380  MD5_Init( &context );
381  MD5_Update( &context, ( unsigned char* )md5Buf, CHALLENGE_LEN + MAX_PASSWORD_LEN );
382  MD5_Final( ( unsigned char* )digest, &context );
383  for ( i = 0; i < RESPONSE_LEN; i++ ) {
384  if ( digest[i] == '\0' ) {
385  digest[i]++;
386  } /* make sure 'string' doesn't end early*/
387  }
388 
389  /* free the array and structure allocated by the rcAuthRequest */
390  //if (authReqOut != NULL) { // JMC cppcheck - redundant nullptr check
391  if ( authReqOut->challenge != NULL ) {
392  free( authReqOut->challenge );
393  }
394  free( authReqOut );
395  //}
396 
397  authRespIn.response = digest;
398  /* the authentication is always for the proxyUser. */
399  authRespIn.username = Conn->proxyUser.userName;
400  strncpy( userNameAndZone, Conn->proxyUser.userName, NAME_LEN );
401  strncat( userNameAndZone, "#", NAME_LEN );
402  strncat( userNameAndZone, Conn->proxyUser.rodsZone, NAME_LEN * 2 );
403  authRespIn.username = userNameAndZone;
404  status = rcAuthResponse( Conn, &authRespIn );
405 
406  if ( status ) {
407  printError( Conn, status, "rcAuthResponse" );
408  return status;
409  }
410  Conn->loggedIn = 1;
411 
412  return 0;
413 }
rodsLog
void rodsLog(int level, const char *formatStr,...)
Definition: rodsLog.cpp:86
irods::plugin_ptr
boost::shared_ptr< plugin_base > plugin_ptr
Definition: irods_first_class_object.hpp:18
rcComm_t
Definition: rcConnect.h:95
NULL
#define NULL
Definition: rodsDef.h:70
irods_configuration_keywords.hpp
rError_t::len
int len
Definition: rodsError.h:25
irods::AUTH_ESTABLISH_CONTEXT
const std::string AUTH_ESTABLISH_CONTEXT("auth_establish_context")
getRodsEnv
int getRodsEnv(rodsEnv *myRodsEnv)
Definition: getRodsEnv.cpp:112
rErrMsg_t
Definition: rodsError.h:19
irods::AUTH_CLIENT_START
const std::string AUTH_CLIENT_START("auth_client_start")
authPluginRequest.h
irods::transform
void transform(const InputC &ic, OutputC &oc, UnaryOperation func)
Definition: irods_re_plugin.hpp:822
hashToStr
int hashToStr(unsigned char *digest, char *digestStr)
Definition: checksum.cpp:206
irods_native_auth_object.hpp
userInfo_t::userName
char userName[64]
Definition: rodsUser.h:66
rcComm_t::proxyUser
userInfo_t proxyUser
Definition: rcConnect.h:103
irods_environment_properties.hpp
getSessionSignatureClientside
char * getSessionSignatureClientside()
Definition: clientLogin.cpp:44
PASS
#define PASS(prev_error_)
Definition: irods_error.hpp:118
pamAuthRequestInp_t::pamPassword
char * pamPassword
Definition: pamAuthRequest.h:8
sslSockComm.h
printError
int printError(rcComm_t *Conn, int status, char *routineName)
Definition: clientLogin.cpp:74
irods::auth_factory
irods::error auth_factory(const std::string &, rError_t *, irods::auth_object_ptr &)
Definition: irods_auth_factory.cpp:16
rcComm_t::rError
rError_t * rError
Definition: rcConnect.h:106
irods::auth_object_ptr
boost::shared_ptr< auth_object > auth_object_ptr
Definition: irods_auth_object.hpp:86
irods::to_env
std::string to_env(const std::string &)
Definition: irods_configuration_parser.cpp:172
checksum.hpp
irods::AUTH_NATIVE_SCHEME
const std::string AUTH_NATIVE_SCHEME("native")
rcGlobalExtern.h
irods::AUTH_INTERFACE
const std::string AUTH_INTERFACE("irods_auth_interface")
rodsErrorName
const char * rodsErrorName(int errorValue, char **subName)
Definition: rodsLog.cpp:373
irods::AUTH_CLIENT_AUTH_REQUEST
const std::string AUTH_CLIENT_AUTH_REQUEST("auth_agent_client_request")
irods::CFG_IRODS_AUTHENTICATION_SCHEME_KW
const std::string CFG_IRODS_AUTHENTICATION_SCHEME_KW("irods_authentication_scheme")
SYS_INVALID_INPUT_PARAM
@ SYS_INVALID_INPUT_PARAM
Definition: rodsErrorTable.h:195
MAX_PASSWORD_LEN
#define MAX_PASSWORD_LEN
Definition: authenticate.h:9
irods_auth_constants.hpp
ProcessType
int ProcessType
Definition: rcGlobal.cpp:16
pamAuthRequestInp_t::pamUser
char * pamUser
Definition: pamAuthRequest.h:7
irods_auth_object.hpp
irods::error::code
long long code() const
Definition: irods_error.cpp:194
rError_t
Definition: rodsError.h:24
irods_auth_factory.hpp
setSessionSignatureClientside
void setSessionSignatureClientside(char *_sig)
Definition: clientLogin.cpp:48
prevChallengeSignatureClient
static char prevChallengeSignatureClient[200]
Definition: clientLogin.cpp:42
obfGetPw
int obfGetPw(char *pw)
Definition: obf.cpp:159
authResponseInp_t
Definition: authResponse.h:6
getLimitedPasswordInp_t::unused1
char * unused1
Definition: getLimitedPassword.h:9
rcComm_t::loggedIn
int loggedIn
Definition: rcConnect.h:100
obfMakeOneWayHash
void obfMakeOneWayHash(int hashType, unsigned const char *inBuf, int inBufSize, unsigned char *outHash)
Definition: obf.cpp:970
irods_pam_auth_object.hpp
obfSavePw
int obfSavePw(int promptOpt, int fileOpt, int printOpt, const char *pwArg)
Definition: obf.cpp:281
sslEnd
int sslEnd(rcComm_t *rcComm)
Definition: sslSockComm.cpp:95
irods::AUTH_PAM_SCHEME
const std::string AUTH_PAM_SCHEME("pam")
pamAuthRequestInp_t
Definition: pamAuthRequest.h:6
authResponseInp_t::username
char * username
Definition: authResponse.h:8
rErrMsg_t::msg
char msg[1024]
Definition: rodsError.h:21
authRequestOut_t
Definition: authRequest.h:11
irods.pypyodbc.status
status
Definition: pypyodbc.py:467
irods_auth_manager.hpp
CLIENT_PT
#define CLIENT_PT
Definition: rodsDef.h:77
userInfo_t::rodsZone
char rodsZone[64]
Definition: rodsUser.h:67
irods::log
void log(const error &)
Definition: irods_log.cpp:13
rcPamAuthRequest
int rcPamAuthRequest(rcComm_t *conn, pamAuthRequestInp_t *pamAuthRequestInp, pamAuthRequestOut_t **pamAuthRequestOut)
Definition: rcPamAuthRequest.cpp:9
clientLogin
int clientLogin(rcComm_t *_comm, const char *_context, const char *_scheme_override)
Definition: clientLogin.cpp:222
clientLoginWithPassword
int clientLoginWithPassword(rcComm_t *Conn, char *password)
Definition: clientLogin.cpp:348
termiosUtil.hpp
LOG_NOTICE
#define LOG_NOTICE
Definition: rodsLog.h:33
irods::error
Definition: irods_error.hpp:23
getLimitedPasswordOut_t::stringToHashWith
char stringToHashWith[50]
Definition: getLimitedPassword.h:14
pamAuthRequestInp_t::timeToLive
int timeToLive
Definition: pamAuthRequest.h:9
rcAuthResponse
int rcAuthResponse(rcComm_t *conn, authResponseInp_t *authResponseInp)
Definition: rcAuthResponse.cpp:35
sslStart
int sslStart(rcComm_t *rcComm)
Definition: sslSockComm.cpp:35
irods_auth_plugin.hpp
getLimitedPasswordOut_t
Definition: getLimitedPassword.h:13
authRequestOut_t::challenge
char * challenge
Definition: authRequest.h:12
rodsClient.h
authResponseInp_t::response
char * response
Definition: authResponse.h:7
RESPONSE_LEN
#define RESPONSE_LEN
Definition: authenticate.h:11
pamAuthRequestOut_t
Definition: pamAuthRequest.h:14
HASH_TYPE_DEFAULT
#define HASH_TYPE_DEFAULT
Definition: obf.h:9
irods_kvp_string_parser.hpp
clientLoginTTL
int clientLoginTTL(rcComm_t *Conn, int ttl)
Definition: clientLogin.cpp:174
pamAuthRequestOut_t::irodsPamPassword
char * irodsPamPassword
Definition: pamAuthRequest.h:15
irods_configuration_parser.hpp
CHALLENGE_LEN
#define CHALLENGE_LEN
Definition: authenticate.h:10
rodsEnv::rodsAuthScheme
char rodsAuthScheme[64]
Definition: getRodsEnv.h:16
rodsEnv
Definition: getRodsEnv.h:8
NAME_LEN
#define NAME_LEN
Definition: rodsDef.h:55
getLimitedPasswordInp_t
Definition: getLimitedPassword.h:7
rError_t::errMsg
rErrMsg_t ** errMsg
Definition: rodsError.h:26
irods::AUTH_CLIENT_AUTH_RESPONSE
const std::string AUTH_CLIENT_AUTH_RESPONSE("auth_agent_client_response")
irods::error::ok
bool ok()
Definition: irods_error.cpp:258
clientLoginPam
int clientLoginPam(rcComm_t *Conn, char *password, int ttl)
Definition: clientLogin.cpp:97
rcGetLimitedPassword
int rcGetLimitedPassword(rcComm_t *conn, getLimitedPasswordInp_t *getLimitedPasswordInp, getLimitedPasswordOut_t **getLimitedPasswordOut)
Definition: rcGetLimitedPassword.cpp:9
irods::auth_ptr
boost::shared_ptr< auth > auth_ptr
Definition: irods_auth_types.hpp:19
irods::error::result
std::string result() const
Definition: irods_error.cpp:201
rcAuthRequest
int rcAuthRequest(rcComm_t *conn, authRequestOut_t **authRequestOut)
Definition: rcAuthRequest.cpp:33
getLimitedPasswordInp_t::ttl
int ttl
Definition: getLimitedPassword.h:8