- Timestamp:
- Oct 31, 2026, 11:50:15 PM (6 days ago)
- Location:
- trunk/BNC
- Files:
-
- 3 added
- 13 edited
-
CHANGELOG.md (modified) (1 diff)
-
src/bnccredentials.cpp (added)
-
src/bnccredentials.h (added)
-
src/bncgetthread.cpp (modified) (6 diffs)
-
src/bncgetthread.h (modified) (1 diff)
-
src/bnchelp.html (modified) (1 diff)
-
src/bncmain.cpp (modified) (1 diff)
-
src/bncsettings.cpp (modified) (1 diff)
-
src/bnctabledlg.cpp (modified) (2 diffs)
-
src/bncwindow.cpp (modified) (6 diffs)
-
src/bncwindow.h (modified) (1 diff)
-
src/src.pri (modified) (2 diffs)
-
src/upload/bncuploadcaster.cpp (modified) (2 diffs)
-
tests/README.md (modified) (2 diffs)
-
tests/tools/cred_check.py (added)
-
tests/tools/fakecaster.py (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/BNC/CHANGELOG.md
r11148 r11153 82 82 - CHANGED: Plot scripts (cmbPlot.pl, pppPlot.pl, compareSP3Plot.pl) delete only the images they created (cmbPlot.pl deleted all PNG files of the input directory) 83 83 - CHANGED: Linux build with stack protector, bounds-checked std containers (_GLIBCXX_ASSERTIONS) and read-only relocations, independent of the distribution's compiler defaults 84 - ADDED: Option 'Credentials files' (key credentialsFile): passwords of Ntrip Broadcasters can be kept in credentials files instead of the configuration file, in netrc format ('machine host[:port] login user password secret', default $NETRC or ~/.netrc) or BNC format ('host port|* user|- password'); several users per host, URLs without user stay anonymous, passwords in the configuration file are used as before 84 85 85 86 ## 2.13.7 (2026-07-31) -
trunk/BNC/src/bncgetthread.cpp
r11066 r11153 65 65 #include "bncnetqueryudp.h" 66 66 #include "bncnetqueryudp0.h" 67 #include "bnccredentials.h" 67 68 #include "bncnetquerys.h" 68 69 #include "bncsettings.h" … … 95 96 _rawFile = 0; 96 97 _mountPoint = mountPoint; 98 _requestUrl = mountPoint; 99 bncCredentials::complete(_requestUrl); // password from a credentials file 97 100 _staID = mountPoint.path().mid(1).toLatin1(); 98 101 _format = format; … … 356 359 msleep(100); //sleep 0.1 sec 357 360 358 _decoder->initRinex(_staID, _ mountPoint, _latitude, _longitude, _nmea,361 _decoder->initRinex(_staID, _requestUrl, _latitude, _longitude, _nmea, 359 362 _ntripVersion); 360 363 … … 768 771 if (_nmea == "yes") { 769 772 if (_serialNMEA == MANUAL_NMEA) { 770 _query->startRequest(_ mountPoint, _manualNMEAString);773 _query->startRequest(_requestUrl, _manualNMEAString); 771 774 _lastNMEA = QDateTime::currentDateTime(); 772 775 } else if (_serialNMEA == AUTO_NMEA) { … … 783 786 if (i2 != -1 && data.size() > i2 + 1) { 784 787 QByteArray gga = data.mid(i1, i2 - i1 + 3); 785 _query->startRequest(_ mountPoint, gga);788 _query->startRequest(_requestUrl, gga); 786 789 _lastNMEA = QDateTime::currentDateTime(); 787 790 } … … 791 794 } 792 795 } else { 793 _query->startRequest(_ mountPoint, "");796 _query->startRequest(_requestUrl, ""); 794 797 } 795 798 -
trunk/BNC/src/bncgetthread.h
r11021 r11153 109 109 GPSDecoder* _decoder; 110 110 bncNetQuery* _query; 111 QUrl _mountPoint; 111 QUrl _mountPoint; // as configured (identifies the stream) 112 QUrl _requestUrl; // with password from a credentials file 112 113 QByteArray _staID; 113 114 QByteArray _format; -
trunk/BNC/src/bnchelp.html
r11148 r11153 2692 2692 and feed in manipulated data. The ignored errors are logged. Better save the CA certificate of the Ntrip 2693 2693 Broadcaster in the 'Path to SSL certificates' directory. 2694 </p> 2695 <p> 2696 Passwords of Ntrip Broadcasters can be kept in 'Credentials files' instead of BNC's configuration file, which 2697 then contains no secrets and can be passed on. Give the user name without password in the stream's URL, e.g. 2698 '//user@products.igs-ip.net:443/SSRA00BKG1', or in the upload settings (empty password). BNC takes the password 2699 from the first matching entry of the credentials files. Streams without user name are retrieved without 2700 authentication, even if a file contains an entry for that host. A password still given in the configuration 2701 file is used as before (with a hint in the logfile), so configurations can be changed step by step. 2702 </p> 2703 <p> 2704 Two file formats are accepted and detected from the content: 2705 <ul> 2706 <li>netrc, as used by curl, wget or git: 'machine products.igs-ip.net login user password secret'. The machine 2707 may also be given as 'host:port' for an account that applies to one port only. The netrc 'default' entry is 2708 not used.</li> 2709 <li>BNC: one entry per line '<host> <port> <user> <password>', port '*' for any port, 2710 user '-' for an entry without user (Ntrip Version 1 upload).</li> 2711 </ul> 2712 Several users per host are distinguished by the user name. An entry for the exact port is preferred over one 2713 for any port. Words containing blanks are quoted: "my secret". A '#' starts a comment. Several files can be 2714 given, separated by commas; default is the file named in the environment variable NETRC, otherwise ~/.netrc. 2715 A file readable for other users is not used (chmod 600). Note that a password containing '%' followed by two 2716 hexadecimal digits is not supported, in the configuration file neither. 2694 2717 </p> 2695 2718 <p><img src="IMG/Figure07.png" width=800 /></p> -
trunk/BNC/src/bncmain.cpp
r11140 r11153 136 136 " sslClientCertPath {Full path to client SSL certificates [character string]}\n" 137 137 " sslIgnoreErrors {Ignore SSL authorization errors [integer number: 0=no,2=yes]}\n" 138 " credentialsFile {Credentials files, netrc or BNC format, default $NETRC or ~/.netrc [character string, comma separated list]}\n" 138 139 "\n" 139 140 "General Panel keys:\n" -
trunk/BNC/src/bncsettings.cpp
r11140 r11153 75 75 setValue_p("sslClientCertPath", ""); 76 76 setValue_p("sslIgnoreErrors", "0"); 77 setValue_p("credentialsFile", ""); 77 78 // General 78 79 setValue_p("logFile", ""); -
trunk/BNC/src/bnctabledlg.cpp
r11116 r11153 47 47 48 48 #include "bnctabledlg.h" 49 #include "bnccredentials.h" 49 50 #include "bncgetthread.h" 50 51 #include "bncnetqueryv1.h" … … 238 239 } 239 240 url.setUserName(QUrl::toPercentEncoding(casterUser)); 240 url.setPassword(QUrl::toPercentEncoding(casterPassword)); 241 QString password = casterPassword; // empty: from a credentials file 242 bncCredentials::complete(casterHost, casterPort, casterUser, password, false, false); 243 url.setPassword(QUrl::toPercentEncoding(password)); 241 244 QByteArray outData; 242 245 query->waitForRequestResult(url, outData); -
trunk/BNC/src/bncwindow.cpp
r11140 r11153 194 194 _sslIgnoreErrorsCheckBox->setCheckState(Qt::CheckState( 195 195 settings.value("sslIgnoreErrors").toInt())); 196 _credentialsFileLineEdit = new QLineEdit(settings.value("credentialsFile").toString()); 196 197 197 198 // General Options … … 828 829 pLayout->addWidget(new QLabel("Ignore SSL authorization errors"), 5, 0); 829 830 pLayout->addWidget(_sslIgnoreErrorsCheckBox, 5, 1, 1, 10); 830 pLayout->addWidget(new QLabel(""), 6, 1); 831 pLayout->setRowStretch(6, 999); 831 pLayout->addWidget(new QLabel("Credentials files"), 6, 0); 832 pLayout->addWidget(_credentialsFileLineEdit, 6, 1, 1, 10); 833 pLayout->addWidget(new QLabel("Default: $NETRC or ~/.netrc"), 6, 11, 1, 20); 834 pLayout->addWidget(new QLabel(""), 7, 1); 835 pLayout->setRowStretch(7, 999); 832 836 833 837 pgroup->setLayout(pLayout); … … 1558 1562 _sslCaCertPathLineEdit->setWhatsThis(tr("<p>Communication with an Ntrip Broadcaster over SSL requires the exchange of server certificates. Specify the path to a directory where you save CA certificates on your system. </p><p>BNC creates from *.crt and *.pem files a CA certificate database, which is used by the socket during the handshake phase to validate the peer's certificate. </p><p>Note that SSL communication is usually done over port 443. <i>[key: sslCaCertPath]</i></p>")); 1559 1563 _sslClientCertPathLineEdit->setWhatsThis(tr("<p>Two-sided communication with an Ntrip Broadcaster over SSL requires in addition the exchange of client certificates. Specify the full path to the client certificates on your system.</p><p></p><p>The file naming convention for client certificates in BNC is as follows: <hostname>.<port>.crt for the certificate and <hostname>.<port>.key for the private key, where <hostname> is without https://. </p><p> If available, the client or personal authentication certificate is presented to the peer during the SSL handshake process. Password protected key files are not supported. </p><p>Don't try communication via two sided SSL if you are not sure whether this is supported by the involved Ntrip Broadcaster. </p><p>Note that SSL communication is usually done over port 443. <i>[key: sslClientCertPath]</i></p>")); 1564 _credentialsFileLineEdit->setWhatsThis(tr("<p>Passwords of Ntrip Broadcasters can be kept in credentials files instead of the configuration file: give the user name without password in the stream's URL (e.g. '//user@products.igs-ip.net:443/SSRA00BKG1') or in the upload settings (empty password). BNC then takes the password from the first matching entry of these files. Streams without user name are retrieved without authentication.</p><p>Two formats are accepted, detected from the file content:<br>netrc: 'machine products.igs-ip.net login user password secret', where the machine may also be given as 'host:port';<br>BNC: one entry per line '<host> <port> <user> <password>', port '*' for any port, user '-' for an entry without user (Ntrip Version 1 upload).</p><p>An entry for the exact port is preferred. Several files can be given, separated by commas; default is the file named in the environment variable NETRC or ~/.netrc. A file readable for other users is not used. A password still given in the configuration file is used as before. <i>[key: credentialsFile]</i></p>")); 1560 1565 _sslIgnoreErrorsCheckBox->setWhatsThis(tr("<p>Tick 'Ignore SSL authorization errors' to accept a server certificate that cannot be verified, e.g. a self-signed certificate or one issued for another host name. The connection is then still encrypted, but the server is not authenticated: anybody able to intercept the connection may receive your user name and password and feed in manipulated data. The ignored errors are logged. Better save the CA certificate of the Ntrip Broadcaster in the 'Path to SSL certificates' directory. <i>[key: sslIgnoreErrors]</i></p>")); 1561 1566 … … 1874 1879 delete _sslClientCertPathLineEdit; 1875 1880 delete _sslIgnoreErrorsCheckBox; 1881 delete _credentialsFileLineEdit; 1876 1882 delete _logFileLineEdit; 1877 1883 delete _rawOutFileLineEdit; … … 2088 2094 settings.setValue("sslClientCertPath", _sslClientCertPathLineEdit->text()); 2089 2095 settings.setValue("sslIgnoreErrors", _sslIgnoreErrorsCheckBox->checkState()); 2096 settings.setValue("credentialsFile", _credentialsFileLineEdit->text()); 2090 2097 2091 2098 QMessageBox msgBox; … … 2404 2411 settings.setValue("sslClientCertPath", _sslClientCertPathLineEdit->text()); 2405 2412 settings.setValue("sslIgnoreErrors", _sslIgnoreErrorsCheckBox->checkState()); 2413 settings.setValue("credentialsFile", _credentialsFileLineEdit->text()); 2406 2414 // General 2407 2415 settings.setValue("logFile", _logFileLineEdit->text()); -
trunk/BNC/src/bncwindow.h
r11140 r11153 141 141 QLineEdit* _sslClientCertPathLineEdit; 142 142 QCheckBox* _sslIgnoreErrorsCheckBox; 143 QLineEdit* _credentialsFileLineEdit; 143 144 QLineEdit* _outFileLineEdit; 144 145 QLineEdit* _outPortLineEdit; -
trunk/BNC/src/src.pri
r11130 r11153 67 67 bncoutf.h bncclockrinex.h bncsp3.h bncsinextro.h \ 68 68 bncbiassinex.h \ 69 bncbytescounter.h bncsslconfig.h reqcdlg.h \ 69 bncbytescounter.h bncsslconfig.h bnccredentials.h reqcdlg.h \ 70 70 ephemeris.h t_prn.h satObs.h \ 71 71 upload/bncrtnetdecoder.h upload/bncuploadcaster.h \ … … 110 110 bncbiassinex.cpp \ 111 111 ephemeris.cpp t_prn.cpp satObs.cpp \ 112 bncbytescounter.cpp bncsslconfig.cpp reqcdlg.cpp \ 112 bncbytescounter.cpp bncsslconfig.cpp bnccredentials.cpp reqcdlg.cpp \ 113 113 upload/bncrtnetdecoder.cpp upload/bncuploadcaster.cpp \ 114 114 upload/bncrawuploadcaster.cpp \ -
trunk/BNC/src/upload/bncuploadcaster.cpp
r11128 r11153 22 22 #include "bncsettings.h" 23 23 #include "bncsslconfig.h" 24 #include "bnccredentials.h" 24 25 25 26 using namespace std; … … 46 47 _userName = userName; 47 48 _password = password; 49 if (!_mountpoint.isEmpty() && !_casterOutHost.isEmpty()) { 50 // empty password: from a credentials file, also without user (Ntrip Version 1) 51 bncCredentials::complete(_casterOutHost, _casterOutPort, _userName, _password, true, true); 52 } 48 53 _outSocket = 0; 49 54 _sOpenTrial = 0; -
trunk/BNC/tests/README.md
r11152 r11153 32 32 | `tools/ssl_check.py` | TLS checks of the Ntrip 2s client and upload (not part of `run_tests.py`) | 33 33 | `tools/net_check.py` | UDP/RTP sender filter and upload status checks on loopback (not part of `run_tests.py`) | 34 | `tools/cred_check.py` | credentials files (`~/.netrc`, BNC format) for download and upload (not part of `run_tests.py`) | 34 35 | `work/` | scratch output, not versioned | 35 36 … … 179 180 as broken. Takes about 2 min. 180 181 182 ## Credentials check 183 184 ``` 185 tests/tools/cred_check.py [--bnc PATH] 186 ``` 187 188 BNC against `tools/fakecaster.py --auth user:password` (other credentials 189 rejected), each scenario with its own `HOME`: password in the configuration 190 file (hint logged), `~/.netrc` with two users for the host, `$NETRC` with 191 `machine host:port` preferred, BNC format file (`credentialsFile`) with exact 192 port preferred over `*` and a quoted password, URL without user (no 193 credentials sent), user without entry, `~/.netrc` readable for others and the 194 netrc `default` entry (not used), Ntrip 1 download, Ntrip 2 upload and 195 Ntrip 1 upload without user. Takes about 2 min. 196 181 197 ## Adding a replay case 182 198 -
trunk/BNC/tests/tools/fakecaster.py
r11130 r11153 16 16 a GET request (BNC as Ntrip client) is answered with the RTCM bytes of the 17 17 given raw file. With --reply an upload is answered with this text instead 18 of the 200 status (e.g. a rejection), and the connection is closed. Failed 18 of the 200 status (e.g. a rejection), and the connection is closed. With 19 --auth user:password (repeatable, ':password' for an Ntrip 1 upload) only 20 these credentials are accepted, others get 401 / 'ERROR - Bad Password'. 21 The user received ("-" without user, "none" without credentials) and failed 19 22 TLS handshakes are reported on stdout. 20 23 """ 21 24 22 25 import argparse 26 import base64 23 27 import os 24 28 import socket … … 70 74 71 75 72 def serve(conn, store, timeout, tls=None, served=None, reply=None): 76 def credentials(header): 77 """(user, password) of a request header, None without credentials.""" 78 lines = header.split(b"\r\n") 79 if lines[0].startswith(b"SOURCE"): 80 parts = lines[0].split(b" ") 81 return "", parts[1].decode("latin-1") if len(parts) > 1 else "" 82 for line in lines[1:]: 83 key, _, value = line.partition(b":") 84 value = value.strip() 85 if key.strip().lower() == b"authorization" and value.lower().startswith(b"basic "): 86 user, _, password = base64.b64decode(value[6:]).decode("latin-1").partition(":") 87 return user, password 88 return None 89 90 91 def serve(conn, store, timeout, tls=None, served=None, reply=None, auth=None): 73 92 conn.settimeout(timeout) 74 93 buf = b"" … … 88 107 header, _, pending = buf.partition(b"\r\n\r\n") 89 108 chunked = b"chunked" in header.lower() 109 cred = credentials(header) 110 ok = auth is None or cred in auth 111 print("auth %s %s" % ("none" if cred is None else (cred[0] or "-"), 112 "accepted" if ok else "rejected"), flush=True) 113 if not ok: 114 conn.sendall(b"ERROR - Bad Password\r\n" if header.startswith(b"SOURCE") 115 else b"HTTP/1.1 401 Unauthorized\r\n\r\n") 116 store.rejected += 1 117 return 90 118 if header.startswith(b"GET") and served is not None: 91 conn.sendall(b"HTTP/1.1 200 OK\r\nNtrip-Version: Ntrip/2.0\r\n" 92 b"Content-Type: gnss/data\r\nConnection: close\r\n\r\n" + served) 119 if b"ntrip-version" in header.lower(): 120 conn.sendall(b"HTTP/1.1 200 OK\r\nNtrip-Version: Ntrip/2.0\r\n" 121 b"Content-Type: gnss/data\r\nConnection: close\r\n\r\n" + served) 122 else: # Ntrip 1 123 conn.sendall(b"ICY 200 OK\r\n\r\n" + served) 93 124 store.served += len(served) 94 125 return … … 134 165 ap.add_argument("--tls-client-ca", help="require a client certificate of this CA") 135 166 ap.add_argument("--serve", help="raw file whose RTCM bytes are sent on GET") 167 ap.add_argument("--auth", action="append", 168 help="accepted user:password (repeatable), others rejected") 136 169 ap.add_argument("--reply", help="answer to uploads instead of 200 ('\\r\\n' escapes allowed)") 137 170 args = ap.parse_args() … … 147 180 if args.reply is not None: 148 181 reply = args.reply.encode("latin-1").decode("unicode_escape").encode("latin-1") 182 auth = None 183 if args.auth: 184 auth = [tuple(a.split(":", 1)) for a in args.auth] 149 185 served = None 150 186 if args.serve: … … 166 202 except socket.timeout: 167 203 break 168 t = threading.Thread(target=serve, args=(conn, store, args.timeout, tls, served, reply), 204 t = threading.Thread(target=serve, args=(conn, store, args.timeout, tls, served, reply, auth), 169 205 daemon=True) 170 206 t.start() … … 177 213 if served is not None: 178 214 print("served %d bytes" % store.served, flush=True) 179 if reply is not None: 180 print("%d upload(s) answered with --reply" % store.rejected, flush=True)215 if reply is not None or auth is not None: 216 print("%d connection(s) rejected" % store.rejected, flush=True) 181 217 return 0 182 218
Note:
See TracChangeset
for help on using the changeset viewer.
