summaryrefslogtreecommitdiff
path: root/packages/google-compute-engine-oslogin/src/include/oslogin_utils.h
blob: ea8beaed071876e48d57067f4a47b5749e06778c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <grp.h>
#include <pthread.h>
#include <pwd.h>

#include <string>
#include <vector>

#define TOTP "TOTP"
#define AUTHZEN "AUTHZEN"
#define INTERNAL_TWO_FACTOR "INTERNAL_TWO_FACTOR"
#define IDV_PREREGISTERED_PHONE "IDV_PREREGISTERED_PHONE"

using std::string;
using std::vector;

namespace oslogin_utils {

// Metadata server URL.
static const char kMetadataServerUrl[] =
    "http://metadata.google.internal/computeMetadata/v1/oslogin/";

// BufferManager encapsulates and manages a buffer and length. This class is not
// thread safe.
class BufferManager {
 public:
  // Create a BufferManager that will dole out chunks of buf as requested.
  BufferManager(char* buf, size_t buflen);

  // Copies a string to the buffer and sets the buffer to point to that
  // string. Copied string is guaranteed to be null-terminated.
  // Returns false and sets errnop if there is not enough space left in the
  // buffer for the string.
  bool AppendString(const string& value, char** buffer, int* errnop);

  // Return a pointer to a buffer of size bytes. Returns NULL and sets errnop to
  // ERANGE if there is not enough space left in the buffer for the request.
  void* Reserve(size_t bytes, int* errnop);

 private:
  // Whether there is space available in the buffer.
  bool CheckSpaceAvailable(size_t bytes_to_write) const;

  char* buf_;
  size_t buflen_;

  // Not copyable or assignable.
  BufferManager& operator=(const BufferManager&);
  BufferManager(const BufferManager&);
};

// Challenge represents a security challenge available to the user.
class Challenge {
 public:
  int id;
  string type;
  string status;
};

class Group {
 public:
  int64_t gid;
  string name;
};

// NssCache caches passwd entries for getpwent_r. This is used to prevent making
// an HTTP call on every getpwent_r invocation. Stores up to cache_size entries
// at a time. This class is not thread safe.
class NssCache {
 public:
  explicit NssCache(int cache_size);

  // Clears and resets the NssCache.
  void Reset();

  // Whether the cache has a next passwd entry.
  bool HasNextPasswd();

  // Whether the cache has reached the last page of the database.
  bool OnLastPage() { return on_last_page_; }

  // Grabs the next passwd entry. Returns true on success. Sets errnop on
  // failure.
  bool GetNextPasswd(BufferManager* buf, passwd* result, int* errnop);

  // Loads a json array of passwd entries in the cache, starting at the
  // beginning of the cache. This will remove all previous entries in the cache.
  // response is expected to be a JSON array of passwd entries. Returns
  // true on success.
  bool LoadJsonArrayToCache(string response);

  // Helper method that effectively implements the getpwent_r nss method. Each
  // call will iterate through the OsLogin database and return the next entry.
  // Internally, the cache will keep track of pages of passwd entries, and will
  // make an http call to the server if necessary to retrieve additional
  // entries. Returns whether passwd retrieval was successful. If true, the
  // passwd result will contain valid data.
  bool NssGetpwentHelper(BufferManager* buf, struct passwd* result,
                         int* errnop);

  // Returns the page token for requesting the next page of passwd entries.
  string GetPageToken() { return page_token_; }

 private:
  // The maximum size of the cache.
  int cache_size_;

  // Vector of passwds. These are represented as stringified json object.
  std::vector<std::string> passwd_cache_;

  // The page token for requesting the next page of passwds.
  std::string page_token_;

  // Index for requesting the next passwd from the cache.
  uint32_t index_;

  // Whether the NssCache has reached the last page of the database.
  bool on_last_page_;

  // Not copyable or assignable.
  NssCache& operator=(const NssCache&);
  NssCache(const NssCache&);
};

// Auto locks and unlocks a given mutex on construction/destruction. Does NOT
// take ownership of the mutex.
class MutexLock {
 public:
  explicit MutexLock(pthread_mutex_t* mutex) : mutex_(mutex) {
    pthread_mutex_lock(mutex_);
  }

  ~MutexLock() { pthread_mutex_unlock(mutex_); }

 private:
  // The mutex to lock/unlock
  pthread_mutex_t* const mutex_;

  // Not copyable or assignable.
  MutexLock& operator=(const MutexLock);
  MutexLock(const MutexLock&);
};

// Callback invoked when Curl completes a request.
size_t OnCurlWrite(void* buf, size_t size, size_t nmemb, void* userp);

// Uses Curl to issue a GET request to the given url. Returns whether the
// request was successful. If successful, the result from the server will be
// stored in response, and the HTTP response code will be stored in http_code.
bool HttpGet(const string& url, string* response, long* http_code);
bool HttpPost(const string& url, const string& data, string* response,
              long* http_code);

// Returns whether user_name is a valid OsLogin user name.
bool ValidateUserName(const string& user_name);

// URL encodes the given parameter. Returns the encoded parameter.
std::string UrlEncode(const string& param);

// Returns true if the given passwd contains valid fields. If pw_dir, pw_shell,
// or pw_passwd are not set, this will populate these entries with default
// values.
bool ValidatePasswd(struct passwd* result, BufferManager* buf, int* errnop);

// Adds users and associated array of char* to provided buffer and store pointer
// to array in result.gr_mem.
bool AddUsersToGroup(std::vector<string> users, struct group* result,
                     BufferManager* buf, int* errnop);

// Iterates through all groups until one matching provided group is found,
// replacing gr_name with a buffermanager provided string.
bool FindGroup(struct group* grp, BufferManager* buf, int* errnop);

// Iterates through all users for a group, storing results in a provided string
// vector.
bool GetUsersForGroup(string groupname, std::vector<string>* users,
                      int* errnop);

// Iterates through all groups for a user, storing results in a provided string
// vector.
bool GetGroupsForUser(string username, std::vector<Group>* groups, int* errnop);

// Parses a JSON groups response, storing results in a provided Group vector.
bool ParseJsonToGroups(const string& json, std::vector<Group>* groups);

// Parses a JSON users response, storing results in a provided string vector.
bool ParseJsonToUsers(const string& json, std::vector<string>* users);

// Parses a JSON LoginProfiles response for SSH keys. Returns a vector of valid
// ssh_keys. A key is considered valid if it's expiration date is greater than
// current unix time.
std::vector<string> ParseJsonToSshKeys(const string& json);

// Parses a JSON object and returns the value associated with a given key.
bool ParseJsonToKey(const string& json, const string& key, string* response);

// Parses a JSON LoginProfiles response and returns the email under the "name"
// field.
bool ParseJsonToEmail(const string& json, string* email);

// Parses a JSON LoginProfiles response and populates the passwd struct with the
// corresponding values set in the JSON object. Returns whether the parse was
// successful or not. If unsuccessful, errnop will also be set.
bool ParseJsonToPasswd(const string& response, struct passwd* result,
                       BufferManager* buf, int* errnop);

// Parses a JSON adminLogin or login response and returns whether the user has
// the requested privilege.
bool ParseJsonToSuccess(const string& json);

// Parses a JSON startSession response into a vector of Challenge objects.
bool ParseJsonToChallenges(const string& json, vector<Challenge>* challenges);

// Calls the startSession API.
bool StartSession(const string& email, string* response);

// Calls the continueSession API.
bool ContinueSession(bool alt, const string& email, const string& user_token,
                     const string& session_id, const Challenge& challenge,
                     string* response);

// Returns user information from the metadata server.
bool GetUser(const string& username, string* response);
}  // namespace oslogin_utils