comparison gensignkey.c @ 1336:efad433418c4

Use atomic key generation in all cases
author Matt Johnston <matt@ucc.asn.au>
date Sat, 19 Nov 2016 00:31:21 +0800
parents 2bb4c662d1c2
children 8747c2b19152
comparison
equal deleted inserted replaced
1335:253c08951b96 1336:efad433418c4
74 default: 74 default:
75 return 0; 75 return 0;
76 } 76 }
77 } 77 }
78 78
79 int signkey_generate(enum signkey_type keytype, int bits, const char* filename) 79 /* if skip_exist is set it will silently return if the key file exists */
80 int signkey_generate(enum signkey_type keytype, int bits, const char* filename, int skip_exist)
80 { 81 {
81 sign_key * key = NULL; 82 sign_key * key = NULL;
82 buffer *buf = NULL; 83 buffer *buf = NULL;
84 char *fn_temp = NULL;
83 int ret = DROPBEAR_FAILURE; 85 int ret = DROPBEAR_FAILURE;
84 if (bits == 0) 86 if (bits == 0)
85 { 87 {
86 bits = get_default_bits(keytype); 88 bits = get_default_bits(keytype);
87 } 89 }
124 126
125 buf_put_priv_key(buf, key, keytype); 127 buf_put_priv_key(buf, key, keytype);
126 sign_key_free(key); 128 sign_key_free(key);
127 key = NULL; 129 key = NULL;
128 buf_setpos(buf, 0); 130 buf_setpos(buf, 0);
129 ret = buf_writefile(buf, filename);
130 131
131 buf_burn(buf); 132 fn_temp = m_malloc(strlen(filename) + 30);
132 buf_free(buf); 133 snprintf(fn_temp, strlen(filename)+30, "%s.tmp%d", filename, getpid());
133 buf = NULL; 134 ret = buf_writefile(buf, fn_temp);
135
136 if (ret == DROPBEAR_FAILURE) {
137 goto out;
138 }
139
140 if (link(fn_temp, filename) < 0) {
141 /* If generating keys on connection (skipexist) it's OK to get EEXIST
142 - we probably just lost a race with another connection to generate the key */
143 if (!(skip_exist && errno == EEXIST)) {
144 dropbear_log(LOG_ERR, "Failed moving key file to %s: %s", filename,
145 strerror(errno));
146 /* XXX fallback to non-atomic copy for some filesystems? */
147 ret = DROPBEAR_FAILURE;
148 goto out;
149 }
150 }
151
152 out:
153 if (buf) {
154 buf_burn(buf);
155 buf_free(buf);
156 }
157
158 if (fn_temp) {
159 unlink(fn_temp);
160 m_free(fn_temp);
161 }
162
134 return ret; 163 return ret;
135 } 164 }