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