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 
14 constexpr char ItemSeparator = ';';
15 constexpr char LineSeparator = '!';
16 
17 // character set same as base64, except for last two (missing are + and / )
18 static const char* b64str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
19 
20 static const std::string KEY_HEADER("Cond_Authentication_Key");
21 
22 static const std::string VERSIONPREFIX("V=");
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 } // namespace cond
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 << VERSIONPREFIX << KEY_FMT_VERSION << std::endl;
100  s << NAMEPREFIX << "<principal_name>" << std::endl;
101  s << OWNERPREFIX << "<owner_name, optional>" << std::endl;
102  s << KEYPREFIX << "<key, leave empty if generated>" << std::endl;
103  //s<<DATEPREFIX<<"<expiring date, optional>"<<std::endl;
104  s << SERVICEPREFIX << "<service_name0>;" << CONNECTIONPREFIX << "<service0_connection_string>;" << USERPREFIX
105  << "<user0_name>;" << PASSWORDPREFIX << "<password0>;" << std::endl;
106  s << SERVICEPREFIX << "<service_name1>;" << CONNECTIONPREFIX << "<service1_connection_string>;" << USERPREFIX
107  << "<user1_name>;" << PASSWORDPREFIX << "<password1>;" << std::endl;
108  s << SERVICEPREFIX << "<service_name2>;" << CONNECTIONPREFIX << "<service2_connection_string>;" << USERPREFIX
109  << "<user2_name>;" << PASSWORDPREFIX << "<password2>;" << std::endl;
110  return s.str();
111 }
112 
113 size_t cond::auth::DecodingKey::init(const std::string& keyFileName, const std::string& password, bool readMode) {
114  if (keyFileName.empty()) {
115  std::string msg("Provided key file name is empty.");
116  throwException(msg, "DecodingKey::init");
117  }
118  m_fileName = keyFileName;
119  m_pwd = password;
120  m_mode = readMode;
121  m_version.clear();
122  m_principalName.clear();
123  m_principalKey.clear();
124  m_owner.clear();
125  m_services.clear();
126  size_t nelem = 0;
127  if (m_mode) {
128  std::ifstream keyFile(m_fileName.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
129  if (keyFile.is_open()) {
130  size_t fsize = keyFile.tellg();
131  unsigned char* buff = (unsigned char*)malloc(fsize);
132  keyFile.seekg(0, std::ios::beg);
133  keyFile.read(reinterpret_cast<char*>(buff), fsize);
134  Cipher cipher(m_pwd);
135  std::string content = cipher.decrypt(buff, fsize);
136  free(buff);
137  // skip the header + line separator
138  if (content.substr(0, KEY_HEADER.size()) != KEY_HEADER) {
139  std::string msg("Provided key content is invalid.");
140  throwException(msg, "DecodingKey::init");
141  }
142  std::stringstream str(content.substr(KEY_HEADER.size() + 1));
143  while (str.good()) {
145  getline(str, line, LineSeparator);
146  if (line.size() > 3) {
147  if (line.substr(0, 2) == VERSIONPREFIX) {
148  m_version = line.substr(2);
149  } else if (line.substr(0, 2) == NAMEPREFIX) {
150  m_principalName = line.substr(2);
151  } else if (line.substr(0, 2) == KEYPREFIX) {
152  m_principalKey = line.substr(2);
153  } else if (line.substr(0, 2) == OWNERPREFIX) {
154  m_owner = line.substr(2);
155  } else if (line.substr(0, 2) == SERVICEPREFIX) {
156  std::stringstream serviceStr(line.substr(2));
157  std::vector<std::string> sdata;
158  while (serviceStr.good()) {
159  sdata.push_back(std::string(""));
160  getline(serviceStr, sdata.back(), ItemSeparator);
161  }
162  std::map<std::string, ServiceCredentials>::iterator iS =
163  m_services.insert(std::make_pair(sdata[0], ServiceCredentials())).first;
164  iS->second.connectionString = sdata[1];
165  iS->second.userName = sdata[2];
166  iS->second.password = sdata[3];
167  nelem++;
168  }
169  }
170  }
171  keyFile.close();
172  if (m_principalName.empty() || m_principalKey.empty()) {
173  std::string msg = "Provided key is invalid.";
174  throwException(msg, "DecodingKey::init");
175  }
176  if (!m_owner.empty()) {
177  std::string currentUser = getLoginName();
178  if (m_owner != currentUser) {
179  m_principalName.clear();
180  m_principalKey.clear();
181  m_owner.clear();
182  m_services.clear();
183  std::string msg = "Provided key is invalid for user=" + currentUser;
184  throwException(msg, "DecodingKey::init");
185  }
186  }
187  } else {
188  std::string msg = "Required Key File \"" + m_fileName + "\" is missing or unreadable.";
189  throwException(msg, "DecodingKey::init");
190  }
191  }
192  return nelem;
193 }
194 
196  size_t nelem = 0;
197  if (inputFileName.empty()) {
198  std::string msg("Provided input file name is empty.");
199  throwException(msg, "DecodingKey::readFromInputFile");
200  }
201  m_version.clear();
202  m_principalName.clear();
203  m_principalKey.clear();
204  m_owner.clear();
205  m_services.clear();
206  std::ifstream inputFile(inputFileName.c_str());
207  if (inputFile.is_open()) {
208  std::map<std::string, std::string> params;
209  while (inputFile.good()) {
211  getline(inputFile, line);
212  params.clear();
213  if (line.size() > 3) {
214  if (line.substr(0, 2) == VERSIONPREFIX) {
215  m_version = line.substr(2);
216  } else if (line.substr(0, 2) == NAMEPREFIX) {
217  m_principalName = line.substr(2);
218  } else if (line.substr(0, 2) == KEYPREFIX) {
219  m_principalKey = line.substr(2);
220  } else if (line.substr(0, 2) == OWNERPREFIX) {
221  m_owner = line.substr(2);
222  } else if (line.substr(0, 2) == SERVICEPREFIX) {
225  ServiceCredentials creds;
227  creds.userName = params[USERPREFIX];
228  creds.password = params[PASSWORDPREFIX];
229  m_services.insert(std::make_pair(serviceName, creds));
230  nelem++;
231  }
232  }
233  }
234  inputFile.close();
235  if (m_principalKey.empty() && generatedKeySize) {
237  m_principalKey = gen.make(generatedKeySize);
238  }
239 
240  } else {
241  std::string msg = "Provided Input File \"" + inputFileName + "\n is invalid.";
242  throwException(msg, "DecodingKey::readFromInputFile");
243  }
244  return nelem;
245 }
246 
247 void cond::auth::DecodingKey::list(std::ostream& out) {
248  out << VERSIONPREFIX << m_version << std::endl;
249  out << NAMEPREFIX << m_principalName << std::endl;
250  out << KEYPREFIX << m_principalKey << std::endl;
251  out << OWNERPREFIX << m_owner << std::endl;
252  for (std::map<std::string, ServiceCredentials>::const_iterator iS = m_services.begin(); iS != m_services.end();
253  iS++) {
254  out << SERVICEPREFIX << iS->first << ";";
255  out << CONNECTIONPREFIX << iS->second.connectionString << ";";
256  out << USERPREFIX << iS->second.userName << ";";
257  out << PASSWORDPREFIX << iS->second.password << ";" << std::endl;
258  }
259 }
260 
262  std::ofstream outFile(m_fileName.c_str(), std::ios::binary);
263  if (outFile.is_open()) {
264  std::stringstream content;
266  if (!m_version.empty()) {
267  content << VERSIONPREFIX << m_version << LineSeparator;
268  }
269  if (!m_principalName.empty()) {
270  content << NAMEPREFIX << m_principalName << LineSeparator;
271  }
272  if (!m_principalKey.empty()) {
273  content << KEYPREFIX << m_principalKey << LineSeparator;
274  }
275  if (!m_owner.empty()) {
276  content << OWNERPREFIX << m_owner << LineSeparator;
277  }
278  for (std::map<std::string, ServiceCredentials>::const_iterator iD = m_services.begin(); iD != m_services.end();
279  ++iD) {
280  content << SERVICEPREFIX << iD->first << ItemSeparator;
281  content << iD->second.connectionString << ItemSeparator;
282  content << iD->second.userName << ItemSeparator;
283  content << iD->second.password << ItemSeparator;
285  }
286  Cipher cipher(m_pwd);
287  unsigned char* out;
288  size_t outSize = cipher.encrypt(content.str(), out);
289  outFile.write(reinterpret_cast<char*>(out), outSize);
290  free(out);
291  } else {
292  std::string msg("");
293  msg += "Provided Key File \"" + m_fileName + "\n is invalid.";
294  throwException(msg, "DecodingKey::flush");
295  }
296  outFile.close();
297 }
298 
301 }
302 
305  const std::string& userName,
306  const std::string& password) {
307  std::map<std::string, ServiceCredentials>::iterator iK = m_services.find(serviceName);
308  if (iK == m_services.end()) {
309  iK = m_services.insert(std::make_pair(serviceName, ServiceCredentials())).first;
310  }
311  iK->second.connectionString = connectionString;
312  iK->second.userName = userName;
313  iK->second.password = password;
314 }
static const std::string KEYPREFIX("K=")
size_t init(const std::string &keyFileName, const std::string &password, bool readMode=true)
Definition: DecodingKey.cc:113
ret
prodAgent to be discontinued
void addService(const std::string &serviceName, const std::string &connectionString, const std::string &userName, const std::string &password)
Definition: DecodingKey.cc:303
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:18
static const std::string VERSIONPREFIX("V=")
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:195
static const char * b64str
Definition: DecodingKey.cc:18
static const std::string KEY_HEADER("Cond_Authentication_Key")
constexpr 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:70
def gen(fragment, howMuch)
Production test section ####.
void addDefaultService(const std::string &connectionString)
Definition: DecodingKey.cc:299
constexpr char ItemSeparator
Definition: DecodingKey.cc:14
static const std::string PASSWORDPREFIX("P=")
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:286
static const std::string CONNECTIONPREFIX("C=")
std::string decrypt(const unsigned char *input, size_t inputSize)
Definition: Cipher.cc:79
Definition: plugin.cc:23
static const std::string NAMEPREFIX("N=")
static const std::string keyFile("/nfshome0/hcalsw/.ReadOMDSKey")
char randomChar()
Definition: DecodingKey.cc:37
void list(std::ostream &out)
Definition: DecodingKey.cc:247
def addService(process, multirun=False)
Definition: FastTimer.py:3
#define str(s)