💾 Archived View for gemini.rmf-dev.com › repo › Vaati › dkee › files › a86297d9f7d117c0e6a9712570698… captured on 2023-04-26 at 13:15:13. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-03-20)

-=-=-=-=-=-=-

0 /*

1 * Copyright (c) 2022 RMF <rawmonk@firemail.cc>

2 *

3 * Permission to use, copy, modify, and distribute this software for any

4 * purpose with or without fee is hereby granted, provided that the above

5 * copyright notice and this permission notice appear in all copies.

6 *

7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES

8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF

9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR

10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES

11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN

12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF

13 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

14 */

15 #include <unistd.h>

16 #include <stdio.h>

17 #include <stdlib.h>

18 #include <string.h>

19 #include <termios.h>

20 #include <signal.h>

21

22 #ifdef __linux__

23 size_t strlcpy(char*, const char*, size_t);

24 #endif

25 int text_box(char*, size_t);

26

27 int popen2(const char *cmd, int *to, int *from, pid_t* pid) {

28 pid_t id;

29 int in[2], out[2];

30

31 if(pipe(in)) return -1;

32 if(pipe(out)) return -1;

33

34 id = fork();

35 if(id < 0) return -1;

36 if(id == 0) {

37 close(in[1]);

38 dup2(in[0], 0);

39 close(out[0]);

40 dup2(out[1], 1);

41 execl("/bin/sh", "sh", "-c", cmd, NULL);

42 exit(-1);

43 }

44 *to = in[1];

45 *from = out[0];

46 close(in[0]);

47 close(out[1]);

48 if (pid) *pid = id;

49 return 0;

50 }

51

52 int start(const char* safe, const char* password, pid_t* pid) {

53 char* data = NULL;

54 char cmd[4096], path[4096], tmp[4096], *ptr;

55 int length = 0, i = 0, j = 0, path_len = 0;

56 int to, from;

57

58 /* read output from keepassxc */

59 snprintf(cmd, sizeof(cmd), "keepassxc-cli ls -R %s", safe);

60

61 if (popen2(cmd, &to, &from, NULL)) return -1;

62 write(to, password, strlen(password));

63 close(to);

64

65 while (1) {

66 int ret;

67 char buf[1024];

68 ret = read(from, buf, sizeof(buf));

69 if (ret < 1) break;

70 data = realloc(data, length + ret);

71 if (!data) return -1;

72 memcpy(&data[length], buf, ret);

73 length += ret;

74 }

75 close(from);

76 if (length <= 0) return -1;

77

78 /* start dmenu and send it formatted password lists */

79 popen2("dmenu -i", &to, &from, NULL);

80

81 /* format keypassxc output */

82 path[0] = '\0';

83 while (i < length) {

84 tmp[j] = data[i];

85 if (!j || tmp[j] != '\n') goto increment;

86 if (tmp[j - 1] == '/') {

87 int depth, pos, slash;

88 tmp[j] = '\0';

89 j = -1;

90 ptr = tmp;

91 while (*ptr == ' ') ptr++;

92 depth = (ptr - tmp)/2;

93

94 pos = 0;

95 slash = 0;

96 if (!depth)

97 path_len = 0;

98 while (depth && pos < path_len) {

99 if (path[pos] == '/') slash++;

100 if (slash == depth) {

101 /* format string... */

102 path_len = pos + 1;

103 break;

104 }

105 pos++;

106 }

107

108 path_len += strlcpy(&path[path_len], ptr,

109 sizeof(path) - path_len);

110 goto increment;

111 }

112 tmp[j + 1] = '\0';

113 ptr = tmp;

114 while (*ptr == ' ') ptr++;

115 write(to, path, path_len);

116 write(to, ptr, j + 1 - (ptr - tmp));

117 j = -1;

118 increment:

119 j++;

120 i++;

121 }

122 close(to);

123

124 /* read dmenu output from dmenu */

125 length = read(from, path, sizeof(path));

126 if (length < 1) return -1;

127 close(from);

128 path[length - 1] = 0;

129

130 /* send dmenu output keypassxc */

131 snprintf(cmd, sizeof(cmd),

132 "keepassxc-cli clip \"%s\" \"%s\"",

133 safe, path);

134 if (popen2(cmd, &to, &from, pid)) return -1;

135 write(to, password, strlen(password));

136 close(to);

137 close(from);

138

139 return 0;

140 }

141

142 int passwd(char* buf, int max) {

143 struct termios term;

144 int c, pos = 0;

145

146 tcgetattr(1, &term);

147 term.c_lflag &= ~ECHO;

148 tcsetattr(1, TCSANOW, &term);

149

150 buf[0] = '\0';

151 while ((c = fgetc(stdin)) != '\n') {

152 buf[pos++] = (char)c;

153 if (pos + 1 >= max)

154 break;

155 }

156 buf[pos] = '\0';

157

158 term.c_lflag |= ECHO;

159 tcsetattr(1, TCSANOW, &term);

160 return pos;

161 }

162

163 int main(int argc, char* argv[]) {

164

165 char password[64];

166 char pid_path[1024];

167 const char* safe = argv[1];

168 sigset_t set;

169 int sig;

170 FILE *f;

171 pid_t pid = -1;

172 int x11 = 1;

173

174 if (argc < 2) {

175 wrong_args:

176 printf("%s [-t] <safe>\n", argv[0]);

177 return -1;

178 }

179 if (argc > 2) {

180 if (strcmp("-t", argv[1])) goto wrong_args;

181 x11 = 0;

182 safe = argv[2];

183 }

184

185 if (x11) {

186 /* X11 */

187 if (text_box(password, sizeof(password))) return -1;

188 } else {

189 /* terminal */

190 printf("Password : ");

191 fflush(stdout);

192 passwd(password, sizeof(password));

193 printf("\n");

194 }

195

196 /* prevent zombie processes */

197 signal(SIGCHLD, SIG_IGN);

198

199 /* exit if invalid password */

200 if (start(safe, password, NULL)) {

201 return -1;

202 }

203

204 /* write pid to file */

205 snprintf(pid_path, sizeof(pid_path),

206 "%s/.cache/.dkee.pid", getenv("HOME"));

207 f = fopen(pid_path, "wb");

208 if (!f) {

209 printf("unable to write pid to : %s\n", pid_path);

210 return -1;

211 }

212

213 daemon(1, 1);

214 fprintf(f, "%d", getpid());

215 fclose(f);

216

217 sigemptyset(&set);

218 sigaddset(&set, SIGUSR1);

219 sigprocmask(SIG_BLOCK, &set, NULL);

220 while (1) {

221 sigwait(&set, &sig);

222 if (pid > 0)

223 kill(pid, SIGKILL);

224 if (sig != SIGUSR1) break;

225 start(safe, password, &pid);

226 }

227

228 remove(pid_path);

229 return 0;

230 }

231