💾 Archived View for gemini.rmf-dev.com › repo › Vaati › dkee › files › 63073a2ba1a9e84913402a95d3291… captured on 2023-09-08 at 16:42:05. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-07-22)

🚧 View Differences

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

Go Back

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 #define MENU "dmenu -i"

23

24 #ifdef __linux__

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

26 #endif

27 int text_box(char*, size_t);

28

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

30 pid_t id;

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

32

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

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

35

36 id = fork();

37 if(id < 0) return -1;

38 if(id == 0) {

39 close(in[1]);

40 dup2(in[0], 0);

41 close(out[0]);

42 dup2(out[1], 1);

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

44 exit(-1);

45 }

46 *to = in[1];

47 *from = out[0];

48 close(in[0]);

49 close(out[1]);

50 if (pid) *pid = id;

51 return 0;

52 }

53

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

55 char* data = NULL;

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

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

58 int to, from;

59

60 /* read output from keepassxc */

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

62

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

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

65 close(to);

66

67 while (1) {

68 int ret;

69 char buf[1024];

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

71 if (ret < 1) break;

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

73 if (!data) return -1;

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

75 length += ret;

76 }

77 close(from);

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

79

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

81 popen2(MENU, &to, &from, NULL);

82

83 /* format keypassxc output */

84 path[0] = '\0';

85 while (i < length) {

86 tmp[j] = data[i];

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

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

89 int depth, pos, slash;

90 tmp[j] = '\0';

91 j = -1;

92 ptr = tmp;

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

94 depth = (ptr - tmp)/2;

95

96 pos = 0;

97 slash = 0;

98 if (!depth)

99 path_len = 0;

100 while (depth && pos < path_len) {

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

102 if (slash == depth) {

103 /* format string... */

104 path_len = pos + 1;

105 break;

106 }

107 pos++;

108 }

109

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

111 sizeof(path) - path_len);

112 goto increment;

113 }

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

115 ptr = tmp;

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

117 write(to, path, path_len);

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

119 j = -1;

120 increment:

121 j++;

122 i++;

123 }

124 close(to);

125

126 /* read dmenu output from dmenu */

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

128 if (length < 1) return -1;

129 close(from);

130 path[length - 1] = 0;

131

132 /* send dmenu output keypassxc */

133 snprintf(cmd, sizeof(cmd),

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

135 safe, path);

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

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

138 close(to);

139 close(from);

140

141 return 0;

142 }

143

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

145 struct termios term;

146 int c, pos = 0;

147

148 tcgetattr(1, &term);

149 term.c_lflag &= ~ECHO;

150 tcsetattr(1, TCSANOW, &term);

151

152 buf[0] = '\0';

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

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

155 if (pos + 1 >= max)

156 break;

157 }

158 buf[pos] = '\0';

159

160 term.c_lflag |= ECHO;

161 tcsetattr(1, TCSANOW, &term);

162 return pos;

163 }

164

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

166

167 char password[64];

168 char pid_path[1024];

169 const char* safe = argv[1];

170 sigset_t set;

171 int sig;

172 FILE *f;

173 pid_t pid = -1;

174 int x11 = 1;

175

176 if (argc < 2) {

177 wrong_args:

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

179 return -1;

180 }

181 if (argc > 2) {

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

183 x11 = 0;

184 safe = argv[2];

185 }

186

187 if (x11) {

188 /* X11 */

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

190 } else {

191 /* terminal */

192 printf("Password : ");

193 fflush(stdout);

194 passwd(password, sizeof(password));

195 printf("\n");

196 }

197

198 /* prevent zombie processes */

199 signal(SIGCHLD, SIG_IGN);

200

201 /* exit if invalid password */

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

203 return -1;

204 }

205

206 /* write pid to file */

207 snprintf(pid_path, sizeof(pid_path),

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

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

210 if (!f) {

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

212 return -1;

213 }

214

215 daemon(1, 1);

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

217 fclose(f);

218

219 sigemptyset(&set);

220 sigaddset(&set, SIGUSR1);

221 sigprocmask(SIG_BLOCK, &set, NULL);

222 while (1) {

223 sigwait(&set, &sig);

224 if (pid > 0)

225 kill(pid, SIGKILL);

226 if (sig != SIGUSR1) break;

227 start(safe, password, &pid);

228 }

229

230 remove(pid_path);

231 return 0;

232 }

233