5 #include <sys/socket.h>
6 #include <netinet/in.h>
11 #include <bsd/unistd.h>
13 void _autossl_ip_parse_error(const char* s
, const size_t len
)
15 fprintf(stderr
, "autossl: failed to parse ip address '%.*s'\n", len
, s
);
18 int connect(int sockfd
, const struct sockaddr_in
*orig_sockaddr
, socklen_t addrlen
)
21 struct in_addr upgrade_ip
;
22 char *upgrade_port_str
;
23 in_port_t upgrade_port
= 0;
26 #define IP_STR_LEN 39+1
27 #define PORT_STR_LEN 5+1
28 char connect_ip
[IP_STR_LEN
];
29 char connect_port
[PORT_STR_LEN
];
32 char *autossl_errno_str
;
34 struct sockaddr_in to_sockaddr
;
35 int (*orig_connect
)(int, const struct sockaddr_in
*, socklen_t
) = dlsym(RTLD_NEXT
, "connect");
39 if(orig_sockaddr
->sin_family
!= AF_INET
) goto stdlib
;
41 upgrade_port_str
= getenv("AUTOSSL_UPGRADE_PORTS");
42 if(upgrade_port_str
== NULL
) goto stdlib
;
45 int upgrade_port_matched
= 0;
46 next_separator
= NULL
;
49 next_separator
= strchrnul(upgrade_port_str
, ' ');
50 upgrade_port
= atoi(upgrade_port_str
);
51 if(upgrade_port
== 0) { fprintf(stderr
, "autossl: failed to parse port number(s): %s\n", upgrade_port_str
); goto error_case
; }
52 if(upgrade_port
== ntohs(orig_sockaddr
->sin_port
)) upgrade_port_matched
= 1;
53 upgrade_port_str
= (char*)(next_separator
+ 1);
55 while(!upgrade_port_matched
&& *next_separator
!= '\0');
57 if(!upgrade_port_matched
) goto stdlib
;
59 upgrade_ip_str
= getenv("AUTOSSL_UPGRADE_IPS");
60 if(upgrade_ip_str
!= NULL
)
62 int upgrade_ip_matched
= 0;
63 char *next_separator
= NULL
;
66 next_separator
= strchrnul(upgrade_ip_str
, ' ');
67 if(inet_aton(upgrade_ip_str
, &upgrade_ip
) == 0)
69 _autossl_ip_parse_error(upgrade_ip_str
, next_separator
- upgrade_ip_str
);
72 if(ntohl(orig_sockaddr
->sin_addr
.s_addr
) == ntohl(upgrade_ip
.s_addr
)) {
73 upgrade_ip_matched
= 1;
75 upgrade_ip_str
= (char*)(next_separator
+ 1);
77 while(!upgrade_ip_matched
&& *next_separator
!= '\0');
79 if(!upgrade_ip_matched
) goto stdlib
;
82 tls_cmd
= getenv("AUTOSSL_TLS_CMD");
83 if(tls_cmd
== NULL
) goto stdlib
;
87 if(socketpair(AF_UNIX
, SOCK_STREAM
, 0, sockpair
) == -1)
89 perror("autossl: sockpair");
93 pid_t childpid
= fork();
96 perror("autossl: fork");
101 /* save the ip and port we wanted to connect to as strings */
102 snprintf(connect_ip
, IP_STR_LEN
, "%s", inet_ntoa(orig_sockaddr
->sin_addr
));
103 snprintf(connect_port
, PORT_STR_LEN
, "%d", ntohs(orig_sockaddr
->sin_port
));
104 /* wire STDIO to the newly created socket */
105 dup2(sockpair
[1], 0);
106 dup2(sockpair
[1], 1);
107 /* leave stderr open */
108 /* close dangling files */
110 execlp(tls_cmd
, tls_cmd
, connect_ip
, connect_port
, NULL
);
115 if(dup2(sockpair
[0], sockfd
) == -1)
117 perror("autossl: dup2");
122 if(!getenv("AUTOSSL_SILENT"))
123 fprintf(stderr
, "autossl: redirecting %s:%d -> fd#%d\n", inet_ntoa(orig_sockaddr
->sin_addr
), ntohs(orig_sockaddr
->sin_port
), sockpair
[0]);
125 /* the caller closes sockfd only, not sockpair[0], so unused open
126 files may pile up eventually in long running programs. */
128 /* childpid process won't be reaped, so don't be scared on the
129 zombie processes, they will be disappear as the main program exits. */
134 autossl_errno_str
= getenv("AUTOSSL_ERRNO");
135 if(autossl_errno_str
)
137 errno
= atoi(autossl_errno_str
);
142 return orig_connect(sockfd
, orig_sockaddr
, addrlen
);