File: osxkeychain_darwin.c

package info (click to toggle)
golang-github-docker-docker-credential-helpers 0.3.0%2Bgit20160601.0.5128fa1-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 184 kB
  • ctags: 104
  • sloc: ansic: 189; makefile: 35; sh: 17
file content (98 lines) | stat: -rw-r--r-- 2,202 bytes parent folder | download
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
#include "osxkeychain_darwin.h"

char *get_error(OSStatus status) {
  char *buf = malloc(128);
  CFStringRef str = SecCopyErrorMessageString(status, NULL);
  int success = CFStringGetCString(str, buf, 128, kCFStringEncodingUTF8);
  if (!success) {
    strncpy(buf, "Unknown error", 128);
  }
  return buf;
}

char *keychain_add(struct Server *server, char *username, char *secret) {
  OSStatus status = SecKeychainAddInternetPassword(
    NULL,
    strlen(server->host), server->host,
    0, NULL,
    strlen(username), username,
    strlen(server->path), server->path,
    server->port,
    server->proto,
    kSecAuthenticationTypeDefault,
    strlen(secret), secret,
    NULL
  );
  if (status) {
    return get_error(status);
  }
  return NULL;
}

char *keychain_get(struct Server *server, unsigned int *username_l, char **username, unsigned int *secret_l, char **secret) {
  char *tmp;
  SecKeychainItemRef item;

  OSStatus status = SecKeychainFindInternetPassword(
    NULL,
    strlen(server->host), server->host,
    0, NULL,
    0, NULL,
    strlen(server->path), server->path,
    server->port,
    server->proto,
    kSecAuthenticationTypeDefault,
    secret_l, (void **)&tmp,
    &item);

  if (status) {
    return get_error(status);
  }

  *secret = strdup(tmp);
  SecKeychainItemFreeContent(NULL, tmp);

  SecKeychainAttributeList list;
  SecKeychainAttribute attr;

  list.count = 1;
  list.attr = &attr;
  attr.tag = kSecAccountItemAttr;

  status = SecKeychainItemCopyContent(item, NULL, &list, NULL, NULL);
  if (status) {
    return get_error(status);
  }

  *username = strdup(attr.data);
  *username_l = attr.length;
  SecKeychainItemFreeContent(&list, NULL);

  return NULL;
}

char *keychain_delete(struct Server *server) {
  SecKeychainItemRef item;

  OSStatus status = SecKeychainFindInternetPassword(
    NULL,
    strlen(server->host), server->host,
    0, NULL,
    0, NULL,
    strlen(server->path), server->path,
    server->port,
    server->proto,
    kSecAuthenticationTypeDefault,
    0, NULL,
    &item);

  if (status) {
    return get_error(status);
  }

  status = SecKeychainItemDelete(item);
  if (status) {
    return get_error(status);
  }
  return NULL;
}