blob: e53cecef2bdb9e9f9a3260ee866ce9066af5dfdb [file] [log] [blame]
Chung-yih Wanga92d5dc2009-06-08 16:34:54 +08001/*
2** Copyright 2008, The Android Open Source Project
3**
4** Licensed under the Apache License, Version 2.0 (the "License");
5** you may not use this file except in compliance with the License.
6** You may obtain a copy of the License at
7**
8** http://www.apache.org/licenses/LICENSE-2.0
9**
10** Unless required by applicable law or agreed to in writing, software
11** distributed under the License is distributed on an "AS IS" BASIS,
12** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13** See the License for the specific language governing permissions and
14** limitations under the License.
15*/
16
17#include "keystore.h"
18
19static DIR *open_keystore(const char *dir)
20{
21 DIR *d;
22 if ((d = opendir(dir)) == NULL) {
23 if (mkdir(dir, 0770) < 0) {
24 LOGE("cannot create dir '%s': %s\n", dir, strerror(errno));
25 unlink(dir);
26 return NULL;
27 }
28 d = open_keystore(dir);
29 }
30 return d;
31}
32
33static int list_files(const char *dir, char reply[REPLY_MAX]) {
34 struct dirent *de;
35 DIR *d;
36
37 if ((d = open_keystore(dir)) == NULL) {
38 return -1;
39 }
40 reply[0]=0;
41 while ((de = readdir(d))) {
42 if (de->d_type != DT_REG) continue;
Chung-yih Wang8fcbada2009-06-10 18:45:14 +080043 if (reply[0] != 0) strlcat(reply, " ", REPLY_MAX);
Chung-yih Wanga92d5dc2009-06-08 16:34:54 +080044 if (strlcat(reply, de->d_name, REPLY_MAX) >= REPLY_MAX) {
45 LOGE("reply is too long(too many files under '%s'\n", dir);
46 return -1;
47 }
48 }
49 closedir(d);
50 return 0;
51}
52
53static int copy_keyfile(const char *keystore, const char *srcfile) {
54 int srcfd, dstfd;
55 int length;
56 char buf[2048];
57 char dstfile[KEYNAME_LENGTH];
58 const char *filename = strrchr(srcfile, '/');
59
60 strlcpy(dstfile, keystore, KEYNAME_LENGTH);
61 strlcat(dstfile, "/", KEYNAME_LENGTH);
62 if (strlcat(dstfile, filename ? filename + 1 : srcfile,
63 KEYNAME_LENGTH) >= KEYNAME_LENGTH) {
64 LOGE("keyname is too long '%s'\n", srcfile);
65 return -1;
66 }
67
68 if ((srcfd = open(srcfile, O_RDONLY)) == -1) {
69 LOGE("Cannot open the original file '%s'\n", srcfile);
70 return -1;
71 }
72 if ((dstfd = open(dstfile, O_CREAT|O_RDWR)) == -1) {
73 LOGE("Cannot open the destination file '%s'\n", dstfile);
74 return -1;
75 }
76 while((length = read(srcfd, buf, 2048)) > 0) {
77 write(dstfd, buf, length);
78 }
79 close(srcfd);
80 close(dstfd);
81 chmod(dstfile, 0440);
82 return 0;
83}
84
85static int install_key(const char *dir, const char *keyfile)
86{
87 struct dirent *de;
88 DIR *d;
89
90 if ((d = open_keystore(dir)) == NULL) {
91 return -1;
92 }
93 return copy_keyfile(dir, keyfile);
94}
95
96static int remove_key(const char *dir, const char *keyfile)
97{
98 char dstfile[KEYNAME_LENGTH];
99
100 strlcpy(dstfile, dir, KEYNAME_LENGTH);
101 strlcat(dstfile, "/", KEYNAME_LENGTH);
102 if (strlcat(dstfile, keyfile, KEYNAME_LENGTH) >= KEYNAME_LENGTH) {
103 LOGE("keyname is too long '%s'\n", keyfile);
104 return -1;
105 }
106 if (unlink(dstfile)) {
107 LOGE("cannot delete '%s': %s\n", dstfile, strerror(errno));
108 return -1;
109 }
110 return 0;
111}
112
113int list_certs(char reply[REPLY_MAX])
114{
115 return list_files(CERTS_DIR, reply);
116}
117
118int list_userkeys(char reply[REPLY_MAX])
119{
120 return list_files(USERKEYS_DIR, reply);
121}
122
123int install_cert(const char *certfile)
124{
125 return install_key(CERTS_DIR, certfile);
126}
127
128int install_userkey(const char *keyfile)
129{
130 return install_key(USERKEYS_DIR, keyfile);
131}
132
133int remove_cert(const char *certfile)
134{
135 return remove_key(CERTS_DIR, certfile);
136}
137
138int remove_userkey(const char *keyfile)
139{
140 return remove_key(USERKEYS_DIR, keyfile);
141}