Add -o and -t options to trust self-signed certificates
parent
a324795b86
commit
e42b3aa08e
37
catgirl.1
37
catgirl.1
|
@ -21,9 +21,11 @@
|
||||||
.Op Fl j Ar join
|
.Op Fl j Ar join
|
||||||
.Op Fl k Ar priv
|
.Op Fl k Ar priv
|
||||||
.Op Fl n Ar nick
|
.Op Fl n Ar nick
|
||||||
|
.Op Fl o Ar chain
|
||||||
.Op Fl p Ar port
|
.Op Fl p Ar port
|
||||||
.Op Fl r Ar real
|
.Op Fl r Ar real
|
||||||
.Op Fl s Ar save
|
.Op Fl s Ar save
|
||||||
|
.Op Fl t Ar trust
|
||||||
.Op Fl u Ar user
|
.Op Fl u Ar user
|
||||||
.Op Fl w Ar pass
|
.Op Fl w Ar pass
|
||||||
.Op Ar config ...
|
.Op Ar config ...
|
||||||
|
@ -216,6 +218,12 @@ Set nickname to
|
||||||
.Ar nick .
|
.Ar nick .
|
||||||
The default nickname is the user's name.
|
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
|
.It Fl p Ar port , Cm port = Ar port
|
||||||
Connect to
|
Connect to
|
||||||
.Ar port .
|
.Ar port .
|
||||||
|
@ -238,6 +246,17 @@ starts with
|
||||||
or
|
or
|
||||||
.Ql \&. .
|
.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
|
.It Fl u Ar user , Cm user = Ar user
|
||||||
Set username to
|
Set username to
|
||||||
.Ar user .
|
.Ar user .
|
||||||
|
@ -287,6 +306,24 @@ sasl-external
|
||||||
.Ed
|
.Ed
|
||||||
.El
|
.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
|
.Sh COMMANDS
|
||||||
Any unique prefix can be used to abbreviate a command.
|
Any unique prefix can be used to abbreviate a command.
|
||||||
For example,
|
For example,
|
||||||
|
|
9
chat.c
9
chat.c
|
@ -140,6 +140,8 @@ int main(int argc, char *argv[]) {
|
||||||
const char *bind = NULL;
|
const char *bind = NULL;
|
||||||
const char *host = NULL;
|
const char *host = NULL;
|
||||||
const char *port = "6697";
|
const char *port = "6697";
|
||||||
|
const char *chain = NULL;
|
||||||
|
const char *trust = NULL;
|
||||||
const char *cert = NULL;
|
const char *cert = NULL;
|
||||||
const char *priv = NULL;
|
const char *priv = NULL;
|
||||||
|
|
||||||
|
@ -167,9 +169,11 @@ int main(int argc, char *argv[]) {
|
||||||
{ .val = 'k', .name = "priv", required_argument },
|
{ .val = 'k', .name = "priv", required_argument },
|
||||||
{ .val = 'l', .name = "log", no_argument },
|
{ .val = 'l', .name = "log", no_argument },
|
||||||
{ .val = 'n', .name = "nick", required_argument },
|
{ .val = 'n', .name = "nick", required_argument },
|
||||||
|
{ .val = 'o', .name = "write-chain", required_argument },
|
||||||
{ .val = 'p', .name = "port", required_argument },
|
{ .val = 'p', .name = "port", required_argument },
|
||||||
{ .val = 'r', .name = "real", required_argument },
|
{ .val = 'r', .name = "real", required_argument },
|
||||||
{ .val = 's', .name = "save", required_argument },
|
{ .val = 's', .name = "save", required_argument },
|
||||||
|
{ .val = 't', .name = "trust", required_argument },
|
||||||
{ .val = 'u', .name = "user", required_argument },
|
{ .val = 'u', .name = "user", required_argument },
|
||||||
{ .val = 'v', .name = "debug", no_argument },
|
{ .val = 'v', .name = "debug", no_argument },
|
||||||
{ .val = 'w', .name = "pass", required_argument },
|
{ .val = 'w', .name = "pass", required_argument },
|
||||||
|
@ -200,9 +204,11 @@ int main(int argc, char *argv[]) {
|
||||||
break; case 'k': priv = optarg;
|
break; case 'k': priv = optarg;
|
||||||
break; case 'l': logEnable = true;
|
break; case 'l': logEnable = true;
|
||||||
break; case 'n': nick = optarg;
|
break; case 'n': nick = optarg;
|
||||||
|
break; case 'o': insecure = true; chain = optarg;
|
||||||
break; case 'p': port = optarg;
|
break; case 'p': port = optarg;
|
||||||
break; case 'r': real = optarg;
|
break; case 'r': real = optarg;
|
||||||
break; case 's': save = optarg;
|
break; case 's': save = optarg;
|
||||||
|
break; case 't': trust = optarg;
|
||||||
break; case 'u': user = optarg;
|
break; case 'u': user = optarg;
|
||||||
break; case 'v': self.debug = true;
|
break; case 'v': self.debug = true;
|
||||||
break; case 'w': pass = optarg;
|
break; case 'w': pass = optarg;
|
||||||
|
@ -231,7 +237,7 @@ int main(int argc, char *argv[]) {
|
||||||
editCompleteAdd();
|
editCompleteAdd();
|
||||||
commandCompleteAdd();
|
commandCompleteAdd();
|
||||||
|
|
||||||
ircConfig(insecure, cert, priv);
|
ircConfig(insecure, trust, cert, priv);
|
||||||
|
|
||||||
uiInitEarly();
|
uiInitEarly();
|
||||||
if (save) {
|
if (save) {
|
||||||
|
@ -249,6 +255,7 @@ int main(int argc, char *argv[]) {
|
||||||
uiDraw();
|
uiDraw();
|
||||||
|
|
||||||
int irc = ircConnect(bind, host, port);
|
int irc = ircConnect(bind, host, port);
|
||||||
|
if (chain) ircWriteChain(chain);
|
||||||
if (pass) ircFormat("PASS :%s\r\n", pass);
|
if (pass) ircFormat("PASS :%s\r\n", pass);
|
||||||
if (sasl) ircFormat("CAP REQ :sasl\r\n");
|
if (sasl) ircFormat("CAP REQ :sasl\r\n");
|
||||||
ircFormat("CAP LS\r\n");
|
ircFormat("CAP LS\r\n");
|
||||||
|
|
5
chat.h
5
chat.h
|
@ -222,8 +222,11 @@ struct Message {
|
||||||
char *params[ParamCap];
|
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);
|
int ircConnect(const char *bind, const char *host, const char *port);
|
||||||
|
void ircWriteChain(const char *path);
|
||||||
void ircRecv(void);
|
void ircRecv(void);
|
||||||
void ircSend(const char *ptr, size_t len);
|
void ircSend(const char *ptr, size_t len);
|
||||||
void ircFormat(const char *format, ...)
|
void ircFormat(const char *format, ...)
|
||||||
|
|
29
irc.c
29
irc.c
|
@ -43,7 +43,9 @@
|
||||||
|
|
||||||
struct tls *client;
|
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();
|
struct tls_config *config = tls_config_new();
|
||||||
if (!config) errx(EX_SOFTWARE, "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_noverifycert(config);
|
||||||
tls_config_insecure_noverifyname(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) {
|
if (cert) {
|
||||||
const char *dirs = NULL;
|
const char *dirs = NULL;
|
||||||
|
@ -149,6 +160,22 @@ int ircConnect(const char *bindHost, const char *host, const char *port) {
|
||||||
return sock;
|
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 };
|
enum { MessageCap = 8191 + 512 };
|
||||||
|
|
||||||
static void debug(const char *pre, const char *line) {
|
static void debug(const char *pre, const char *line) {
|
||||||
|
|
Loading…
Reference in New Issue