CMS 3D CMS Logo

DecodingKey.cc
Go to the documentation of this file.
5 //
6 #include <sstream>
7 #include <cstring>
8 #include <fstream>
9 #include <vector>
10 #include <pwd.h>
11 #include <ctime>
12 #include <unistd.h>
13 
16 
17 // character set same as base64, except for last two (missing are + and / )
18 static const char* b64str =
19  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
20 
21 static const std::string KEY_HEADER("Cond_Authentication_Key");
22 
23 static const std::string NAMEPREFIX("N=");
24 static const std::string KEYPREFIX("K=");
25 static const std::string OWNERPREFIX("O=");
26 
27 static const std::string DATEPREFIX("D=");
28 
29 static const std::string SERVICEPREFIX("S=");
30 static const std::string CONNECTIONPREFIX("C=");
31 static const std::string USERPREFIX("U=");
32 static const std::string PASSWORDPREFIX("P=");
33 
34 static const std::string DEFAULT_SERVICE("Cond_Default_Service");
35 
36 namespace cond {
37  char randomChar(){
38  int irand = ::rand()%(::strlen(b64str));
39  return b64str[irand];
40  }
41 
43  std::string loginName("");
44  struct passwd* userp = ::getpwuid(::getuid());
45  if(userp) {
46  char* uName = userp->pw_name;
47  if(uName){
48  loginName += uName;
49  }
50  }
51  if(loginName.empty()){
52  std::string msg("Cannot determine login name.");
53  throwException(msg,"DecodingKey::getLoginName");
54  }
55  return loginName;
56  }
57 
58  void parseLineForNamedParams( const std::string& line, std::map<std::string,std::string>& params ){
59  std::stringstream str( line );
60  std::string paramName("");
61  std::string paramValue("");
62  while( str.good() ){
63  std::string item("");
64  getline( str, item, ItemSeparator);
65  if( item.size()>3 ){
66  paramName = item.substr(0,2);
67  paramValue = item.substr(2);
68  params.insert( std::make_pair( paramName, paramValue ) );
69  }
70  }
71  }
72 
73 }
74 
76  ::srand( m_iteration+2 );
77  int rseed = ::rand();
78  int seed = ::time( nullptr)%10 + rseed;
79  ::srand( seed );
80  std::string ret("");
81  for( size_t i=0;i<keySize; i++ ){
82  ret += randomChar();
83  }
84  m_iteration++;
85  return ret;
86 }
87 
89  ::srand( m_iteration+2 );
90  int rseed = ::rand();
91  int seed = ::time( nullptr)%10 + rseed;
92  ::srand( seed );
93  size_t sz = rand()%maxSize;
94  return make( sz );
95 }
96 
98  std::stringstream s;
99  s<<NAMEPREFIX<<"<principal_name>"<<std::endl;
100  s<<OWNERPREFIX<<"<owner_name, optional>"<<std::endl;
101  s<<KEYPREFIX<<"<key, leave empty if generated>"<<std::endl;
102  //s<<DATEPREFIX<<"<expiring date, optional>"<<std::endl;
103  s<<SERVICEPREFIX<<"<service_name0>;"<<CONNECTIONPREFIX<<"<service0_connection_string>;"<<USERPREFIX<<"<user0_name>;"<<PASSWORDPREFIX<<"<password0>;"<<std::endl;
104  s<<SERVICEPREFIX<<"<service_name1>;"<<CONNECTIONPREFIX<<"<service1_connection_string>;"<<USERPREFIX<<"<user1_name>;"<<PASSWORDPREFIX<<"<password1>;"<<std::endl;
105  s<<SERVICEPREFIX<<"<service_name2>;"<<CONNECTIONPREFIX<<"<service2_connection_string>;"<<USERPREFIX<<"<user2_name>;"<<PASSWORDPREFIX<<"<password2>;"<<std::endl;
106  return s.str();
107 }
108 
109 size_t cond::auth::DecodingKey::init( const std::string& keyFileName, const std::string& password, bool readMode ){
110  if(keyFileName.empty()){
111  std::string msg("Provided key file name is empty.");
112  throwException(msg,"DecodingKey::init");
113  }
114  m_fileName = keyFileName;
115  m_pwd = password;
116  m_mode = readMode;
117  m_principalName.clear();
118  m_principalKey.clear();
119  m_owner.clear();
120  m_services.clear();
121  size_t nelem = 0;
122  if( m_mode ){
123  std::ifstream keyFile (m_fileName.c_str(),std::ios::in|std::ios::binary|std::ios::ate);
124  if (keyFile.is_open()){
125  size_t fsize = keyFile.tellg();
126  unsigned char* buff = (unsigned char*)malloc( fsize );
127  keyFile.seekg (0, std::ios::beg);
128  keyFile.read (reinterpret_cast<char*>(buff), fsize);
129  Cipher cipher( m_pwd );
130  std::string content = cipher.decrypt( buff, fsize );
131  free ( buff );
132  // skip the header + line separator
133  if( content.substr( 0, KEY_HEADER.size() )!=KEY_HEADER ){
134  std::string msg("Provided key content is invalid.");
135  throwException(msg,"DecodingKey::init");
136  }
137  std::stringstream str( content.substr( KEY_HEADER.size()+1) );
138  while( str.good() ){
140  getline ( str, line,LineSeparator );
141  if(line.size()>3 ){
142  if( line.substr(0,2)==NAMEPREFIX ){
143  m_principalName = line.substr(2);
144  } else if ( line.substr(0,2)== KEYPREFIX ){
145  m_principalKey = line.substr(2);
146  } else if ( line.substr(0,2)== OWNERPREFIX ){
147  m_owner = line.substr(2);
148  } else if ( line.substr(0,2)== SERVICEPREFIX ){
149  std::stringstream serviceStr( line.substr(2) );
150  std::vector<std::string> sdata;
151  while( serviceStr.good() ){
152  sdata.push_back( std::string("") );
153  getline( serviceStr, sdata.back(), ItemSeparator);
154  }
155  std::map< std::string, ServiceCredentials >::iterator iS = m_services.insert( std::make_pair( sdata[0], ServiceCredentials() ) ).first;
156  iS->second.connectionString = sdata[1];
157  iS->second.userName = sdata[2];
158  iS->second.password = sdata[3];
159  nelem++;
160  }
161  }
162  }
163  keyFile.close();
164  if( m_principalName.empty() || m_principalKey.empty() ){
165  std::string msg = "Provided key is invalid.";
166  throwException(msg,"DecodingKey::init");
167  }
168  if( !m_owner.empty() ){
169  std::string currentUser = getLoginName();
170  if(m_owner != currentUser ){
171  m_principalName.clear();
172  m_principalKey.clear();
173  m_owner.clear();
174  m_services.clear();
175  std::string msg = "Provided key is invalid for user=" + currentUser;
176  throwException(msg,"DecodingKey::init");
177  }
178  }
179  } else {
180  std::string msg = "Required Key File \""+m_fileName+"\" is missing or unreadable.";
181  throwException(msg,"DecodingKey::init");
182  }
183  }
184  return nelem;
185 }
186 
188  size_t nelem = 0;
189  if(inputFileName.empty()){
190  std::string msg("Provided input file name is empty.");
191  throwException(msg,"DecodingKey::readFromInputFile");
192  }
193  m_principalName.clear();
194  m_principalKey.clear();
195  m_owner.clear();
196  m_services.clear();
197  std::ifstream inputFile (inputFileName.c_str());
198  if (inputFile.is_open()){
199  std::map<std::string,std::string> params;
200  while ( inputFile.good() ){
202  getline (inputFile, line);
203  params.clear();
204  if(line.size()>3 ){
205  if( line.substr(0,2)==NAMEPREFIX ){
206  m_principalName = line.substr(2);
207  } else if ( line.substr(0,2)== KEYPREFIX ){
208  m_principalKey = line.substr(2);
209  } else if ( line.substr(0,2)== OWNERPREFIX ){
210  m_owner = line.substr(2);
211  } else if ( line.substr(0,2)== SERVICEPREFIX ){
212  parseLineForNamedParams( line, params );
214  ServiceCredentials creds;
215  creds.connectionString = params[ CONNECTIONPREFIX ];
216  creds.userName = params[ USERPREFIX ];
217  creds.password = params[ PASSWORDPREFIX ];
218  m_services.insert( std::make_pair( serviceName, creds ) );
219  nelem++;
220  }
221  }
222  }
223  inputFile.close();
224  if( m_principalKey.empty() && generatedKeySize){
226  m_principalKey = gen.make( generatedKeySize );
227  }
228 
229  } else {
230  std::string msg = "Provided Input File \""+inputFileName+"\n is invalid.";
231  throwException(msg,"DecodingKey::readFromInputFile");
232  }
233  return nelem;
234 }
235 
236 void cond::auth::DecodingKey::list( std::ostream& out ){
237  out <<NAMEPREFIX<<m_principalName<<std::endl;
238  out <<KEYPREFIX<<m_principalKey<<std::endl;
239  out <<OWNERPREFIX<<m_owner<<std::endl;
240  for( std::map< std::string, ServiceCredentials >::const_iterator iS = m_services.begin();
241  iS != m_services.end(); iS++ ){
242  out <<SERVICEPREFIX<<iS->first<<";";
243  out <<CONNECTIONPREFIX<<iS->second.connectionString<<";";
244  out <<USERPREFIX<<iS->second.userName<<";";
245  out <<PASSWORDPREFIX<<iS->second.password<<";"<<std::endl;
246  }
247 }
248 
250  std::ofstream outFile ( m_fileName.c_str(),std::ios::binary);
251  if (outFile.is_open()){
252  std::stringstream content;
253  content << KEY_HEADER << LineSeparator;
254  if( !m_principalName.empty() ){
255  content << NAMEPREFIX << m_principalName << LineSeparator;
256  }
257  if( !m_principalKey.empty() ){
258  content << KEYPREFIX << m_principalKey << LineSeparator;
259  }
260  if( !m_owner.empty() ){
261  content << OWNERPREFIX << m_owner << LineSeparator;
262  }
263  for( std::map< std::string, ServiceCredentials >::const_iterator iD = m_services.begin();
264  iD != m_services.end(); ++iD ){
265  content << SERVICEPREFIX << iD->first << ItemSeparator;
266  content << iD->second.connectionString << ItemSeparator;
267  content << iD->second.userName << ItemSeparator;
268  content << iD->second.password << ItemSeparator;
269  content << LineSeparator;
270  }
271  Cipher cipher( m_pwd );
272  unsigned char* out;
273  size_t outSize = cipher.encrypt( content.str(), out );
274  outFile.write( reinterpret_cast<char*>(out),outSize);
275  free (out );
276  } else {
277  std::string msg("");
278  msg += "Provided Key File \""+m_fileName+"\n is invalid.";
279  throwException(msg,"DecodingKey::flush");
280  }
281  outFile.close();
282 }
283 
285  addService( DEFAULT_SERVICE, connectionString, "", "" );
286 }
287 
289  const std::string& connectionString,
290  const std::string& userName,
291  const std::string& password ){
292  std::map< std::string, ServiceCredentials >::iterator iK = m_services.find( serviceName );
293  if( iK == m_services.end() ){
294  iK = m_services.insert( std::make_pair( serviceName, ServiceCredentials() ) ).first;
295  }
296  iK->second.connectionString = connectionString;
297  iK->second.userName = userName;
298  iK->second.password = password;
299 }
300 
static const std::string KEYPREFIX("K=")
size_t init(const std::string &keyFileName, const std::string &password, bool readMode=true)
Definition: DecodingKey.cc:109
void addService(const std::string &serviceName, const std::string &connectionString, const std::string &userName, const std::string &password)
Definition: DecodingKey.cc:288
void parseLineForNamedParams(const std::string &line, std::map< std::string, std::string > &params)
Definition: DecodingKey.cc:58
S make(const edm::ParameterSet &cfg)
std::string getLoginName()
Definition: DecodingKey.cc:42
static const std::string USERPREFIX("U=")
static const std::string serviceName
void throwException(const std::string &message, const std::string &methodName)
Definition: Exception.cc:21
static const std::string SERVICEPREFIX("S=")
static const std::string DATEPREFIX("D=")
size_t createFromInputFile(const std::string &inputFileName, size_t generatedKeySize=0)
Definition: DecodingKey.cc:187
#define constexpr
static const char * b64str
Definition: DecodingKey.cc:18
static const std::string KEY_HEADER("Cond_Authentication_Key")
char LineSeparator
Definition: DecodingKey.cc:15
static const std::string DEFAULT_SERVICE("Cond_Default_Service")
static std::string templateFile()
Definition: DecodingKey.cc:97
size_t encrypt(const std::string &input, unsigned char *&output)
Definition: Cipher.cc:71
def gen(fragment, howMuch)
Production test section ####.
void addDefaultService(const std::string &connectionString)
Definition: DecodingKey.cc:284
static const std::string PASSWORDPREFIX("P=")
char ItemSeparator
Definition: DecodingKey.cc:14
static const std::string OWNERPREFIX("O=")
std::string makeWithRandomSize(size_t maxSize)
Definition: DecodingKey.cc:88
std::string make(size_t keySize)
Definition: DecodingKey.cc:75
tuple msg
Definition: mps_check.py:278
static const std::string CONNECTIONPREFIX("C=")
std::string decrypt(const unsigned char *input, size_t inputSize)
Definition: Cipher.cc:79
Definition: plugin.cc:24
static const std::string NAMEPREFIX("N=")
static const std::string keyFile("/nfshome0/hcalsw/.ReadOMDSKey")
Signal rand(Signal arg)
Definition: vlib.cc:442
char randomChar()
Definition: DecodingKey.cc:37
void list(std::ostream &out)
Definition: DecodingKey.cc:236
#define str(s)