diff options
| author | C. McEnroe | 2021-01-09 19:11:57 -0500 | 
|---|---|---|
| committer | C. McEnroe | 2021-01-09 19:11:57 -0500 | 
| commit | e42b3aa08e3706ecb87ca76254fbab51cccf3390 (patch) | |
| tree | ab0232c0962f1f7ca6649ff1b0767b5c2f2ee120 | |
| parent | a324795b8610b7c3e5626ac72d202ce6207066d7 (diff) | |
Add -o and -t options to trust self-signed certificates
| -rw-r--r-- | catgirl.1 | 37 | ||||
| -rw-r--r-- | chat.c | 9 | ||||
| -rw-r--r-- | chat.h | 5 | ||||
| -rw-r--r-- | irc.c | 29 | 
4 files changed, 77 insertions, 3 deletions
@@ -21,9 +21,11 @@  .Op Fl j Ar join  .Op Fl k Ar priv  .Op Fl n Ar nick +.Op Fl o Ar chain  .Op Fl p Ar port  .Op Fl r Ar real  .Op Fl s Ar save +.Op Fl t Ar trust  .Op Fl u Ar user  .Op Fl w Ar pass  .Op Ar config ... @@ -216,6 +218,12 @@ Set nickname to  .Ar nick .  The default nickname is the user's name.  . +.It Fl o Ar chain +Write the server certificate chain to +.Ar chain +in PEM format. +This temporarily disables certificate verification! +.  .It Fl p Ar port , Cm port = Ar port  Connect to  .Ar port . @@ -238,6 +246,17 @@ starts with  or  .Ql \&. .  . +.It Fl t Ar path , Cm trust = Ar path +Trust the certificate loaded from +.Ar path . +Server name verification is disabled. +The +.Ar path +is searched for in the same manner +as configuration files. +See +.Sx Connecting to Servers with Self-signed Certificates . +.  .It Fl u Ar user , Cm user = Ar user  Set username to  .Ar user . @@ -287,6 +306,24 @@ sasl-external  .Ed  .El  . +.Ss Connecting to Servers with Self-signed Certificates +.Bl -enum +.It +Connect to the server +and write its certificate to a file: +.Bd -literal -offset indent +catgirl -h irc.example.org -o ~/.config/catgirl/example.pem +.Ed +.It +Configure +.Nm +to trust the certificate: +.Bd -literal -offset indent +trust = example.pem +# or: catgirl -t example.pem +.Ed +.El +.  .Sh COMMANDS  Any unique prefix can be used to abbreviate a command.  For example, @@ -140,6 +140,8 @@ int main(int argc, char *argv[]) {  	const char *bind = NULL;  	const char *host = NULL;  	const char *port = "6697"; +	const char *chain = NULL; +	const char *trust = NULL;  	const char *cert = NULL;  	const char *priv = NULL; @@ -167,9 +169,11 @@ int main(int argc, char *argv[]) {  		{ .val = 'k', .name = "priv", required_argument },  		{ .val = 'l', .name = "log", no_argument },  		{ .val = 'n', .name = "nick", required_argument }, +		{ .val = 'o', .name = "write-chain", required_argument },  		{ .val = 'p', .name = "port", required_argument },  		{ .val = 'r', .name = "real", required_argument },  		{ .val = 's', .name = "save", required_argument }, +		{ .val = 't', .name = "trust", required_argument },  		{ .val = 'u', .name = "user", required_argument },  		{ .val = 'v', .name = "debug", no_argument },  		{ .val = 'w', .name = "pass", required_argument }, @@ -200,9 +204,11 @@ int main(int argc, char *argv[]) {  			break; case 'k': priv = optarg;  			break; case 'l': logEnable = true;  			break; case 'n': nick = optarg; +			break; case 'o': insecure = true; chain = optarg;  			break; case 'p': port = optarg;  			break; case 'r': real = optarg;  			break; case 's': save = optarg; +			break; case 't': trust = optarg;  			break; case 'u': user = optarg;  			break; case 'v': self.debug = true;  			break; case 'w': pass = optarg; @@ -231,7 +237,7 @@ int main(int argc, char *argv[]) {  	editCompleteAdd();  	commandCompleteAdd(); -	ircConfig(insecure, cert, priv); +	ircConfig(insecure, trust, cert, priv);  	uiInitEarly();  	if (save) { @@ -249,6 +255,7 @@ int main(int argc, char *argv[]) {  	uiDraw();  	int irc = ircConnect(bind, host, port); +	if (chain) ircWriteChain(chain);  	if (pass) ircFormat("PASS :%s\r\n", pass);  	if (sasl) ircFormat("CAP REQ :sasl\r\n");  	ircFormat("CAP LS\r\n"); @@ -222,8 +222,11 @@ struct Message {  	char *params[ParamCap];  }; -void ircConfig(bool insecure, const char *cert, const char *priv); +void ircConfig( +	bool insecure, const char *trust, const char *cert, const char *priv +);  int ircConnect(const char *bind, const char *host, const char *port); +void ircWriteChain(const char *path);  void ircRecv(void);  void ircSend(const char *ptr, size_t len);  void ircFormat(const char *format, ...) @@ -43,7 +43,9 @@  struct tls *client; -void ircConfig(bool insecure, const char *cert, const char *priv) { +void ircConfig( +	bool insecure, const char *trust, const char *cert, const char *priv +) {  	struct tls_config *config = tls_config_new();  	if (!config) errx(EX_SOFTWARE, "tls_config_new"); @@ -59,6 +61,15 @@ void ircConfig(bool insecure, const char *cert, const char *priv) {  		tls_config_insecure_noverifycert(config);  		tls_config_insecure_noverifyname(config);  	} +	if (trust) { +		tls_config_insecure_noverifyname(config); +		const char *dirs = NULL; +		for (const char *path; NULL != (path = configPath(&dirs, trust));) { +			error = tls_config_set_ca_file(config, path); +			if (!error) break; +		} +		if (error) errx(EX_NOINPUT, "%s: %s", trust, tls_config_error(config)); +	}  	if (cert) {  		const char *dirs = NULL; @@ -149,6 +160,22 @@ int ircConnect(const char *bindHost, const char *host, const char *port) {  	return sock;  } +void ircWriteChain(const char *path) { +	FILE *file = fopen(path, "w"); +	if (!file) err(EX_CANTCREAT, "%s", path); + +	int n = fprintf(file, "subject= %s\n", tls_peer_cert_subject(client)); +	if (n < 0) err(EX_IOERR, "%s", path); + +	size_t len; +	const byte *pem = tls_peer_cert_chain_pem(client, &len); +	len = fwrite(pem, len, 1, file); +	if (!len) err(EX_IOERR, "%s", path); + +	int error = fclose(file); +	if (error) err(EX_IOERR, "%s", path); +} +  enum { MessageCap = 8191 + 512 };  static void debug(const char *pre, const char *line) {  | 
