{"action":"created","comment":{"url":"https://api.github.com/repos/google/libpam-policycache/pulls/comments/82306276","pull_request_review_id":3224435,"id":82306276,"diff_hunk":"@@ -0,0 +1,173 @@\n+/**\n+ * Copyright 2016 Google Inc. All rights reserved.\n+ *\n+ * Licensed under the Apache License, Version 2.0 (the \"License\");\n+ * you may not use this file except in compliance with the License.\n+ * You may obtain a copy of the License at\n+ *\n+ *     http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing, software\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+ * See the License for the specific language governing permissions and\n+ * limitations under the License.\n+ */\n+ \n+ \n+#include \"storage.h\"\n+#include \"module.h\"\n+#include \"entry.h\"\n+#include <string.h>\n+#include <stdio.h>\n+#include <shadow.h>\n+\n+#define SH_TMPFILE \"/etc/nshadow\"\n+\n+/**\n+ * CreateEntryFromShadowHash:\n+ * @username: Username containing the shadow hash.\n+ * @sdhash: User's hashed shadow password.\n+ */\n+gboolean CreateEntryFromShadowHash(const char *username, char *sdhash) {\n+  // Create a new Cache Entry.\n+  CacheEntry *entry = CacheEntryNew();\n+  GBytes* gbytes = g_bytes_new(sdhash, strlen(sdhash));\n+  // Set the newly created entry hash using the /etc/shadow hash.\n+  CacheEntryHashSet(entry, CACHE_ENTRY_ALGORITHM_CRYPT, gbytes, NULL);\n+  g_bytes_unref(gbytes);\n+  GError *error = NULL;\n+  CacheStorage *storage = CacheStorageNew(DEFAULT_STORAGE_PATH);\n+  if (!CacheStoragePutEntry(storage, username, entry, &error))\n+      goto done;\n+\n+  done:\n+    if (error) {\n+      fprintf(stderr, \"Failed to create Cache Entry.\\n\");\n+      return FALSE;\n+    } else {\n+      fprintf(stdout, \"Successfully created Cache Entry.\\n\");\n+      return TRUE;\n+    }\n+}\n+\n+/**\n+ * UpdateShadowHash:\n+ * @username: Username to blank out hashed shadow password.\n+ * @towhat: What to changed the hashed password to.\n+ */\n+gboolean UpdateShadowHash(const gchar *username, gchar *towhat) {\n+  struct spwd *stmpent = NULL;\n+\n+  FILE *pwfile, *opwfile;\n+  int error = 0;\n+  int oldmask = umask(077);\n+  int wroteentry = 0;\n+\n+\n+  pwfile = fopen(SH_TMPFILE, \"w\");\n+  umask(oldmask);\n+  if (pwfile == NULL) {\n+    error = 1;\n+    goto done;\n+  }\n+\n+  opwfile = fopen(\"/etc/shadow\", \"r\");\n+  if (opwfile == NULL) {\n+    fclose(pwfile);\n+    error = 1;\n+    goto done;\n+  }\n+\n+  // stmpent -- Read next shadow entry from STREAM.\n+  stmpent = fgetspent(opwfile);\n+  // Loop through /etc/shadow file\n+  while (stmpent) {\n+    if (!strcmp(stmpent->sp_namp, username)) {\n+      // Create entry from shadow hash if username matches an entry.\n+      CreateEntryFromShadowHash(username, stmpent->sp_pwdp);\n+      // Set encrypted password to towhat\n+      stmpent->sp_pwdp = towhat;\n+      stmpent->sp_lstchg = time(NULL) / (60 * 60 * 24);\n+      // Check that an entry was written.\n+      wroteentry = 1;\n+      fprintf(stdout, \"Set password %s for %s\\n\", stmpent-> sp_pwdp, username);\n+    }\n+\n+    if (putspent(stmpent, pwfile)) {\n+      fprintf(stderr, \"Error writting entry to shadow file\\n\");\n+      error = 1;\n+      break;\n+    }\n+\n+    stmpent = fgetspent(opwfile);\n+  }\n+\n+  fclose(opwfile);\n+\n+  done:\n+    if (!error) {\n+      // Move tmp file contents into the real file.\n+      if (!rename(SH_TMPFILE, \"/etc/shadow\"))\n+          fprintf(stdout, \"Password changed for %s\\n\", username);\n+      else\n+          error = 1;\n+    }\n+\n+  if (!error) {\n+    fprintf(stdout, \"Successfully updated shadow file.\\n\");\n+    return TRUE;\n+  } else {\n+    unlink(SH_TMPFILE);\n+    fprintf(stderr, \"Failed to update shadow file.\\n\");\n+    return FALSE;\n+  }\n+}\n+\n+int main(int argc, char *argv[]) {\n+  int exit_code = 0;\n+  GError *error = NULL;\n+  GOptionContext *context = NULL;\n+ \n+  // TODO(mcclunge): Add option to disable hash password instead of just remove.\n+  static gboolean remove = FALSE; \n+  static gchar* username = NULL;\n+  static GOptionEntry entries[] = \n+    {\n+\t{ \"remove\", 'r', 0, G_OPTION_ARG_NONE, &remove, \"Remove shadow hash password for a given user.\"},","path":"src/import-shadow-hash.c","position":137,"original_position":137,"commit_id":"f3b72c1e94bfa4d77e7078f81b9d6115b6ae8945","original_commit_id":"f3b72c1e94bfa4d77e7078f81b9d6115b6ae8945","user":{"login":"vonhollen","id":409031,"avatar_url":"https://avatars.githubusercontent.com/u/409031?v=3","gravatar_id":"","url":"https://api.github.com/users/vonhollen","html_url":"https://github.com/vonhollen","followers_url":"https://api.github.com/users/vonhollen/followers","following_url":"https://api.github.com/users/vonhollen/following{/other_user}","gists_url":"https://api.github.com/users/vonhollen/gists{/gist_id}","starred_url":"https://api.github.com/users/vonhollen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vonhollen/subscriptions","organizations_url":"https://api.github.com/users/vonhollen/orgs","repos_url":"https://api.github.com/users/vonhollen/repos","events_url":"https://api.github.com/users/vonhollen/events{/privacy}","received_events_url":"https://api.github.com/users/vonhollen/received_events","type":"User","site_admin":false},"body":"Instead of removing the old shadow entry immediately, we want to lock it for the first phase of the rollout and unlock it if a rollback is needed. It might be wise to make this file simply read /etc/shadow and add a cache entry instead of actually modifying /etc/shadow. Then we can do the /etc/shadow modification with \"passwd --lock\", \"passwd --unlock\", etc.","created_at":"2016-10-06T23:28:22Z","updated_at":"2016-10-06T23:28:22Z","html_url":"https://github.com/google/libpam-policycache/pull/17#discussion_r82306276","pull_request_url":"https://api.github.com/repos/google/libpam-policycache/pulls/17","_links":{"self":{"href":"https://api.github.com/repos/google/libpam-policycache/pulls/comments/82306276"},"html":{"href":"https://github.com/google/libpam-policycache/pull/17#discussion_r82306276"},"pull_request":{"href":"https://api.github.com/repos/google/libpam-policycache/pulls/17"}}},"pull_request":{"url":"https://api.github.com/repos/google/libpam-policycache/pulls/17","id":87030110,"html_url":"https://github.com/google/libpam-policycache/pull/17","diff_url":"https://github.com/google/libpam-policycache/pull/17.diff","patch_url":"https://github.com/google/libpam-policycache/pull/17.patch","issue_url":"https://api.github.com/repos/google/libpam-policycache/issues/17","number":17,"state":"open","locked":false,"title":"Add import-shadow-hash.c","user":{"login":"mcclunge","id":22484410,"avatar_url":"https://avatars.githubusercontent.com/u/22484410?v=3","gravatar_id":"","url":"https://api.github.com/users/mcclunge","html_url":"https://github.com/mcclunge","followers_url":"https://api.github.com/users/mcclunge/followers","following_url":"https://api.github.com/users/mcclunge/following{/other_user}","gists_url":"https://api.github.com/users/mcclunge/gists{/gist_id}","starred_url":"https://api.github.com/users/mcclunge/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mcclunge/subscriptions","organizations_url":"https://api.github.com/users/mcclunge/orgs","repos_url":"https://api.github.com/users/mcclunge/repos","events_url":"https://api.github.com/users/mcclunge/events{/privacy}","received_events_url":"https://api.github.com/users/mcclunge/received_events","type":"User","site_admin":false},"body":"Add ability to import hashed passwords in /etc/shadow and import them into policycache.","created_at":"2016-09-27T23:21:34Z","updated_at":"2016-10-06T23:39:12Z","closed_at":null,"merged_at":null,"merge_commit_sha":"bee257b5413a1c4b890ffb0dc3e6b1edb2826d48","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/google/libpam-policycache/pulls/17/commits","review_comments_url":"https://api.github.com/repos/google/libpam-policycache/pulls/17/comments","review_comment_url":"https://api.github.com/repos/google/libpam-policycache/pulls/comments{/number}","comments_url":"https://api.github.com/repos/google/libpam-policycache/issues/17/comments","statuses_url":"https://api.github.com/repos/google/libpam-policycache/statuses/f3b72c1e94bfa4d77e7078f81b9d6115b6ae8945","head":{"label":"google:mcclunge-dev","ref":"mcclunge-dev","sha":"f3b72c1e94bfa4d77e7078f81b9d6115b6ae8945","user":{"login":"google","id":1342004,"avatar_url":"https://avatars.githubusercontent.com/u/1342004?v=3","gravatar_id":"","url":"https://api.github.com/users/google","html_url":"https://github.com/google","followers_url":"https://api.github.com/users/google/followers","following_url":"https://api.github.com/users/google/following{/other_user}","gists_url":"https://api.github.com/users/google/gists{/gist_id}","starred_url":"https://api.github.com/users/google/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/google/subscriptions","organizations_url":"https://api.github.com/users/google/orgs","repos_url":"https://api.github.com/users/google/repos","events_url":"https://api.github.com/users/google/events{/privacy}","received_events_url":"https://api.github.com/users/google/received_events","type":"Organization","site_admin":false},"repo":{"id":20077211,"name":"libpam-policycache","full_name":"google/libpam-policycache","owner":{"login":"google","id":1342004,"avatar_url":"https://avatars.githubusercontent.com/u/1342004?v=3","gravatar_id":"","url":"https://api.github.com/users/google","html_url":"https://github.com/google","followers_url":"https://api.github.com/users/google/followers","following_url":"https://api.github.com/users/google/following{/other_user}","gists_url":"https://api.github.com/users/google/gists{/gist_id}","starred_url":"https://api.github.com/users/google/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/google/subscriptions","organizations_url":"https://api.github.com/users/google/orgs","repos_url":"https://api.github.com/users/google/repos","events_url":"https://api.github.com/users/google/events{/privacy}","received_events_url":"https://api.github.com/users/google/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/google/libpam-policycache","description":"Password caching module with advanced policies for PAM.","fork":false,"url":"https://api.github.com/repos/google/libpam-policycache","forks_url":"https://api.github.com/repos/google/libpam-policycache/forks","keys_url":"https://api.github.com/repos/google/libpam-policycache/keys{/key_id}","collaborators_url":"https://api.github.com/repos/google/libpam-policycache/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/google/libpam-policycache/teams","hooks_url":"https://api.github.com/repos/google/libpam-policycache/hooks","issue_events_url":"https://api.github.com/repos/google/libpam-policycache/issues/events{/number}","events_url":"https://api.github.com/repos/google/libpam-policycache/events","assignees_url":"https://api.github.com/repos/google/libpam-policycache/assignees{/user}","branches_url":"https://api.github.com/repos/google/libpam-policycache/branches{/branch}","tags_url":"https://api.github.com/repos/google/libpam-policycache/tags","blobs_url":"https://api.github.com/repos/google/libpam-policycache/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/google/libpam-policycache/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/google/libpam-policycache/git/refs{/sha}","trees_url":"https://api.github.com/repos/google/libpam-policycache/git/trees{/sha}","statuses_url":"https://api.github.com/repos/google/libpam-policycache/statuses/{sha}","languages_url":"https://api.github.com/repos/google/libpam-policycache/languages","stargazers_url":"https://api.github.com/repos/google/libpam-policycache/stargazers","contributors_url":"https://api.github.com/repos/google/libpam-policycache/contributors","subscribers_url":"https://api.github.com/repos/google/libpam-policycache/subscribers","subscription_url":"https://api.github.com/repos/google/libpam-policycache/subscription","commits_url":"https://api.github.com/repos/google/libpam-policycache/commits{/sha}","git_commits_url":"https://api.github.com/repos/google/libpam-policycache/git/commits{/sha}","comments_url":"https://api.github.com/repos/google/libpam-policycache/comments{/number}","issue_comment_url":"https://api.github.com/repos/google/libpam-policycache/issues/comments{/number}","contents_url":"https://api.github.com/repos/google/libpam-policycache/contents/{+path}","compare_url":"https://api.github.com/repos/google/libpam-policycache/compare/{base}...{head}","merges_url":"https://api.github.com/repos/google/libpam-policycache/merges","archive_url":"https://api.github.com/repos/google/libpam-policycache/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/google/libpam-policycache/downloads","issues_url":"https://api.github.com/repos/google/libpam-policycache/issues{/number}","pulls_url":"https://api.github.com/repos/google/libpam-policycache/pulls{/number}","milestones_url":"https://api.github.com/repos/google/libpam-policycache/milestones{/number}","notifications_url":"https://api.github.com/repos/google/libpam-policycache/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/google/libpam-policycache/labels{/name}","releases_url":"https://api.github.com/repos/google/libpam-policycache/releases{/id}","deployments_url":"https://api.github.com/repos/google/libpam-policycache/deployments","created_at":"2014-05-22T21:14:25Z","updated_at":"2016-10-06T06:33:16Z","pushed_at":"2016-09-27T23:21:34Z","git_url":"git://github.com/google/libpam-policycache.git","ssh_url":"git@github.com:google/libpam-policycache.git","clone_url":"https://github.com/google/libpam-policycache.git","svn_url":"https://github.com/google/libpam-policycache","homepage":"","size":131,"stargazers_count":16,"watchers_count":16,"language":"C","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":6,"mirror_url":null,"open_issues_count":4,"forks":6,"open_issues":4,"watchers":16,"default_branch":"master"}},"base":{"label":"google:master","ref":"master","sha":"160b1c35109aa3ad31d46fda038b734c31442c64","user":{"login":"google","id":1342004,"avatar_url":"https://avatars.githubusercontent.com/u/1342004?v=3","gravatar_id":"","url":"https://api.github.com/users/google","html_url":"https://github.com/google","followers_url":"https://api.github.com/users/google/followers","following_url":"https://api.github.com/users/google/following{/other_user}","gists_url":"https://api.github.com/users/google/gists{/gist_id}","starred_url":"https://api.github.com/users/google/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/google/subscriptions","organizations_url":"https://api.github.com/users/google/orgs","repos_url":"https://api.github.com/users/google/repos","events_url":"https://api.github.com/users/google/events{/privacy}","received_events_url":"https://api.github.com/users/google/received_events","type":"Organization","site_admin":false},"repo":{"id":20077211,"name":"libpam-policycache","full_name":"google/libpam-policycache","owner":{"login":"google","id":1342004,"avatar_url":"https://avatars.githubusercontent.com/u/1342004?v=3","gravatar_id":"","url":"https://api.github.com/users/google","html_url":"https://github.com/google","followers_url":"https://api.github.com/users/google/followers","following_url":"https://api.github.com/users/google/following{/other_user}","gists_url":"https://api.github.com/users/google/gists{/gist_id}","starred_url":"https://api.github.com/users/google/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/google/subscriptions","organizations_url":"https://api.github.com/users/google/orgs","repos_url":"https://api.github.com/users/google/repos","events_url":"https://api.github.com/users/google/events{/privacy}","received_events_url":"https://api.github.com/users/google/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/google/libpam-policycache","description":"Password caching module with advanced policies for PAM.","fork":false,"url":"https://api.github.com/repos/google/libpam-policycache","forks_url":"https://api.github.com/repos/google/libpam-policycache/forks","keys_url":"https://api.github.com/repos/google/libpam-policycache/keys{/key_id}","collaborators_url":"https://api.github.com/repos/google/libpam-policycache/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/google/libpam-policycache/teams","hooks_url":"https://api.github.com/repos/google/libpam-policycache/hooks","issue_events_url":"https://api.github.com/repos/google/libpam-policycache/issues/events{/number}","events_url":"https://api.github.com/repos/google/libpam-policycache/events","assignees_url":"https://api.github.com/repos/google/libpam-policycache/assignees{/user}","branches_url":"https://api.github.com/repos/google/libpam-policycache/branches{/branch}","tags_url":"https://api.github.com/repos/google/libpam-policycache/tags","blobs_url":"https://api.github.com/repos/google/libpam-policycache/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/google/libpam-policycache/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/google/libpam-policycache/git/refs{/sha}","trees_url":"https://api.github.com/repos/google/libpam-policycache/git/trees{/sha}","statuses_url":"https://api.github.com/repos/google/libpam-policycache/statuses/{sha}","languages_url":"https://api.github.com/repos/google/libpam-policycache/languages","stargazers_url":"https://api.github.com/repos/google/libpam-policycache/stargazers","contributors_url":"https://api.github.com/repos/google/libpam-policycache/contributors","subscribers_url":"https://api.github.com/repos/google/libpam-policycache/subscribers","subscription_url":"https://api.github.com/repos/google/libpam-policycache/subscription","commits_url":"https://api.github.com/repos/google/libpam-policycache/commits{/sha}","git_commits_url":"https://api.github.com/repos/google/libpam-policycache/git/commits{/sha}","comments_url":"https://api.github.com/repos/google/libpam-policycache/comments{/number}","issue_comment_url":"https://api.github.com/repos/google/libpam-policycache/issues/comments{/number}","contents_url":"https://api.github.com/repos/google/libpam-policycache/contents/{+path}","compare_url":"https://api.github.com/repos/google/libpam-policycache/compare/{base}...{head}","merges_url":"https://api.github.com/repos/google/libpam-policycache/merges","archive_url":"https://api.github.com/repos/google/libpam-policycache/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/google/libpam-policycache/downloads","issues_url":"https://api.github.com/repos/google/libpam-policycache/issues{/number}","pulls_url":"https://api.github.com/repos/google/libpam-policycache/pulls{/number}","milestones_url":"https://api.github.com/repos/google/libpam-policycache/milestones{/number}","notifications_url":"https://api.github.com/repos/google/libpam-policycache/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/google/libpam-policycache/labels{/name}","releases_url":"https://api.github.com/repos/google/libpam-policycache/releases{/id}","deployments_url":"https://api.github.com/repos/google/libpam-policycache/deployments","created_at":"2014-05-22T21:14:25Z","updated_at":"2016-10-06T06:33:16Z","pushed_at":"2016-09-27T23:21:34Z","git_url":"git://github.com/google/libpam-policycache.git","ssh_url":"git@github.com:google/libpam-policycache.git","clone_url":"https://github.com/google/libpam-policycache.git","svn_url":"https://github.com/google/libpam-policycache","homepage":"","size":131,"stargazers_count":16,"watchers_count":16,"language":"C","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":6,"mirror_url":null,"open_issues_count":4,"forks":6,"open_issues":4,"watchers":16,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/google/libpam-policycache/pulls/17"},"html":{"href":"https://github.com/google/libpam-policycache/pull/17"},"issue":{"href":"https://api.github.com/repos/google/libpam-policycache/issues/17"},"comments":{"href":"https://api.github.com/repos/google/libpam-policycache/issues/17/comments"},"review_comments":{"href":"https://api.github.com/repos/google/libpam-policycache/pulls/17/comments"},"review_comment":{"href":"https://api.github.com/repos/google/libpam-policycache/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/google/libpam-policycache/pulls/17/commits"},"statuses":{"href":"https://api.github.com/repos/google/libpam-policycache/statuses/f3b72c1e94bfa4d77e7078f81b9d6115b6ae8945"}}}}
{"actor":{"display_login":"vonhollen"}}