4646#include <fcntl.h>
4747#include "lws-acme-client.h"
4848
49+ #if !defined(WIN32 )
50+ #include <sys/socket.h>
51+ #include <sys/un.h>
52+
53+ static int
54+ acme_ipc_save_payload (const char * uds_path , const char * req , const char * domain , const char * filename , const char * payload , size_t payload_len )
55+ {
56+ int fd = socket (AF_UNIX , SOCK_STREAM , 0 );
57+ if (fd < 0 ) return 1 ;
58+ struct sockaddr_un addr ;
59+ memset (& addr , 0 , sizeof (addr ));
60+ addr .sun_family = AF_UNIX ;
61+ strncpy (addr .sun_path , uds_path , sizeof (addr .sun_path ) - 1 );
62+ if (connect (fd , (struct sockaddr * )& addr , sizeof (addr )) < 0 ) {
63+ close (fd );
64+ return 1 ;
65+ }
66+
67+ char header [512 ];
68+ int hlen = lws_snprintf (header , sizeof (header ), "{\"req\":\"%s\",\"domain\":\"%s\",\"subdomain\":\"%s\",\"zone\":\"" , req , domain , filename );
69+ write (fd , header , (size_t )hlen );
70+
71+ for (size_t i = 0 ; i < payload_len ; i ++ ) {
72+ char c = payload [i ];
73+ if (c == '\n' ) { write (fd , "\\n" , 2 ); }
74+ else if (c == '\r' ) { write (fd , "\\r" , 2 ); }
75+ else if (c == '"' ) { write (fd , "\\\"" , 2 ); }
76+ else if (c == '\\' ) { write (fd , "\\\\" , 2 ); }
77+ else { write (fd , & c , 1 ); }
78+ }
79+ write (fd , "\"}\n" , 3 );
80+
81+ char resp [256 ];
82+ read (fd , resp , sizeof (resp ));
83+ close (fd );
84+ return 0 ;
85+ }
86+ #else
87+ static int
88+ acme_ipc_save_payload (const char * uds_path , const char * req , const char * domain , const char * filename , const char * payload , size_t payload_len )
89+ {
90+ return 1 ;
91+ }
92+ #endif
93+
4994typedef enum {
5095 ACME_STATE_DIRECTORY , /* get the directory JSON using GET + parse */
5196 ACME_STATE_NEW_NONCE , /* get the replay nonce */
@@ -706,9 +751,42 @@ lws_acme_load_create_auth_keys(struct per_vhost_data__lws_acme_client *vhd,
706751 lwsl_notice ("...keypair generated\n" );
707752
708753 if (lws_jwk_save (& vhd -> jwk , vhd -> active_cert -> pvop [LWS_TLS_SET_AUTH_PATH ])) {
709- lwsl_vhost_warn (vhd -> vhost , "unable to save %s" ,
710- vhd -> active_cert -> pvop [LWS_TLS_SET_AUTH_PATH ]);
711- return 1 ;
754+ lwsl_vhost_notice (vhd -> vhost , "falling back to ACME footprint IPC to save %s" , vhd -> active_cert -> pvop [LWS_TLS_SET_AUTH_PATH ]);
755+ char tmp_path [256 ];
756+ lws_snprintf (tmp_path , sizeof (tmp_path ), "/tmp/lws-acme-auth-%d.jwk" , getpid ());
757+ if (!lws_jwk_save (& vhd -> jwk , tmp_path )) {
758+ int fd = open (tmp_path , O_RDONLY );
759+ int success = 0 ;
760+ if (fd >= 0 ) {
761+ struct stat st ;
762+ if (!fstat (fd , & st ) && st .st_size > 0 ) {
763+ char * buf = malloc ((size_t )st .st_size );
764+ if (buf && read (fd , buf , (size_t )st .st_size ) == st .st_size ) {
765+ const char * fp = vhd -> active_cert -> pvop [LWS_TLS_SET_AUTH_PATH ];
766+ const char * fn = strrchr (fp , '/' );
767+ if (fn ) fn ++ ; else fn = fp ;
768+ int r = acme_ipc_save_payload ("/var/run/lws-dnssec-monitor.sock" ,
769+ "save_auth_key" ,
770+ vhd -> active_cert -> pvop [LWS_TLS_REQ_ELEMENT_COMMON_NAME ],
771+ fn ,
772+ buf , (size_t )st .st_size );
773+ if (!r ) success = 1 ;
774+ }
775+ if (buf ) free (buf );
776+ }
777+ close (fd );
778+ }
779+ unlink (tmp_path );
780+ if (!success ) {
781+ lwsl_vhost_warn (vhd -> vhost , "unable to save %s via footprint IPC" ,
782+ vhd -> active_cert -> pvop [LWS_TLS_SET_AUTH_PATH ]);
783+ return 1 ;
784+ }
785+ } else {
786+ lwsl_vhost_warn (vhd -> vhost , "unable to save %s" ,
787+ vhd -> active_cert -> pvop [LWS_TLS_SET_AUTH_PATH ]);
788+ return 1 ;
789+ }
712790 }
713791
714792 return 0 ;
@@ -1775,15 +1853,21 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason,
17751853#endif
17761854 , 0600 );
17771855 if (fd_cert < 0 ) {
1778- lwsl_vhost_err (vhd -> vhost , "unable to create cert file %s" , cert_ts );
1779- goto failed ;
1780- }
1781-
1782- n = lws_plat_write_cert (vhd -> vhost , 0 , fd_cert , ac -> buf , (size_t )ac -> cpos );
1783- close (fd_cert );
1784- if (n ) {
1785- lwsl_vhost_err (vhd -> vhost , "unable to write ACME cert!" );
1786- goto failed ;
1856+ lwsl_vhost_notice (vhd -> vhost , "falling back to IPC footprint to save %s" , cert_ts );
1857+ const char * fn = strrchr (cert_ts , '/' );
1858+ if (fn ) fn ++ ; else fn = cert_ts ;
1859+ int r = acme_ipc_save_payload ("/var/run/lws-dnssec-monitor.sock" , "save_cert" , vhd -> active_cert -> pvop [LWS_TLS_REQ_ELEMENT_COMMON_NAME ], fn , ac -> buf , (size_t )ac -> cpos );
1860+ if (r ) {
1861+ lwsl_vhost_err (vhd -> vhost , "unable to create cert file %s" , cert_ts );
1862+ goto failed ;
1863+ }
1864+ } else {
1865+ n = lws_plat_write_cert (vhd -> vhost , 0 , fd_cert , ac -> buf , (size_t )ac -> cpos );
1866+ close (fd_cert );
1867+ if (n ) {
1868+ lwsl_vhost_err (vhd -> vhost , "unable to write ACME cert!" );
1869+ goto failed ;
1870+ }
17871871 }
17881872
17891873 fd_key = lws_open (key_ts , LWS_O_WRONLY | LWS_O_CREAT | LWS_O_TRUNC
@@ -1792,25 +1876,42 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason,
17921876#endif
17931877 , 0600 );
17941878 if (fd_key < 0 ) {
1795- lwsl_vhost_err (vhd -> vhost , "unable to create key file %s" , key_ts );
1796- goto failed ;
1797- }
1798-
1799- n = lws_plat_write_cert (vhd -> vhost , 1 , fd_key , ac -> alloc_privkey_pem , ac -> len_privkey_pem );
1800- close (fd_key );
1801- if (n ) {
1802- lwsl_vhost_err (vhd -> vhost , "unable to write ACME key!" );
1803- goto failed ;
1879+ lwsl_vhost_notice (vhd -> vhost , "falling back to IPC footprint to save %s" , key_ts );
1880+ const char * fn = strrchr (key_ts , '/' );
1881+ if (fn ) fn ++ ; else fn = key_ts ;
1882+ int r = acme_ipc_save_payload ("/var/run/lws-dnssec-monitor.sock" , "save_key" , vhd -> active_cert -> pvop [LWS_TLS_REQ_ELEMENT_COMMON_NAME ], fn , ac -> alloc_privkey_pem , ac -> len_privkey_pem );
1883+ if (r ) {
1884+ lwsl_vhost_err (vhd -> vhost , "unable to create key file %s" , key_ts );
1885+ goto failed ;
1886+ }
1887+ } else {
1888+ n = lws_plat_write_cert (vhd -> vhost , 1 , fd_key , ac -> alloc_privkey_pem , ac -> len_privkey_pem );
1889+ close (fd_key );
1890+ if (n ) {
1891+ lwsl_vhost_err (vhd -> vhost , "unable to write ACME key!" );
1892+ goto failed ;
1893+ }
18041894 }
18051895
18061896 fd_full = lws_open (full_ts , LWS_O_WRONLY | LWS_O_CREAT | LWS_O_TRUNC
18071897#ifdef WIN32
18081898 | O_BINARY
18091899#endif
18101900 , 0600 );
1811- if (fd_full >= 0 ) {
1901+ if (fd_full < 0 ) {
1902+ lwsl_vhost_notice (vhd -> vhost , "falling back to IPC footprint to save %s" , full_ts );
1903+ const char * fn = strrchr (full_ts , '/' );
1904+ if (fn ) fn ++ ; else fn = full_ts ;
1905+ int r = acme_ipc_save_payload ("/var/run/lws-dnssec-monitor.sock" , "save_cert" , vhd -> active_cert -> pvop [LWS_TLS_REQ_ELEMENT_COMMON_NAME ], fn , ac -> buf , (size_t )cpos_fullchain );
1906+ if (r ) {
1907+ lwsl_vhost_err (vhd -> vhost , "unable to create fullchain file %s" , full_ts );
1908+ }
1909+ } else {
18121910 n = lws_plat_write_cert (vhd -> vhost , 0 , fd_full , ac -> buf , (size_t )cpos_fullchain );
18131911 close (fd_full );
1912+ if (n ) {
1913+ lwsl_vhost_err (vhd -> vhost , "unable to write ACME fullchain cert!" );
1914+ }
18141915 }
18151916
18161917 /* Symlink update */
0 commit comments