mate_install: do not depend on deprecated GStreamer 0.10
[oi-userland.git] / components / network / hpn-ssh / patches / 0010-PAM-enhancements-for-Solaris.patch
blobe42f2bed04dc2d04badf30bd496bf1815aadcc24
1 --- hpn-ssh-hpn-18.4.2/auth-pam.c.orig
2 +++ hpn-ssh-hpn-18.4.2/auth-pam.c
3 @@ -689,6 +689,66 @@
4 sshpam_handle = NULL;
7 +#ifdef PAM_ENHANCEMENT
8 +char *
9 +derive_pam_service_name(Authctxt *authctxt)
11 + char *svcname = xmalloc(BUFSIZ);
13 + /*
14 + * If PamServiceName is set we use that for everything, including
15 + * SSHv1
16 + */
17 + if (options.pam_service_name != NULL) {
18 + (void) strlcpy(svcname, options.pam_service_name, BUFSIZ);
19 + return (svcname);
20 + }
22 + char *method_name = authctxt->authmethod_name;
24 + if (!method_name)
25 + fatal("Userauth method unknown while starting PAM");
27 + /*
28 + * For SSHv2 we use "sshd-<userauth name>
29 + * The "sshd" prefix can be changed via the PAMServicePrefix
30 + * sshd_config option.
31 + */
32 + if (strcmp(method_name, "none") == 0) {
33 + snprintf(svcname, BUFSIZ, "%s-none",
34 + options.pam_service_prefix);
35 + }
36 + if (strcmp(method_name, "password") == 0) {
37 + snprintf(svcname, BUFSIZ, "%s-password",
38 + options.pam_service_prefix);
39 + }
40 + if (strcmp(method_name, "keyboard-interactive") == 0) {
41 + /* "keyboard-interactive" is too long, shorten it */
42 + snprintf(svcname, BUFSIZ, "%s-kbdint",
43 + options.pam_service_prefix);
44 + }
45 + if (strcmp(method_name, "publickey") == 0) {
46 + /* "publickey" is too long, shorten it */
47 + snprintf(svcname, BUFSIZ, "%s-pubkey",
48 + options.pam_service_prefix);
49 + }
50 + if (strcmp(method_name, "hostbased") == 0) {
51 + snprintf(svcname, BUFSIZ, "%s-hostbased",
52 + options.pam_service_prefix);
53 + }
54 + if (strncmp(method_name, "gssapi-", 7) == 0) {
55 + /*
56 + * Although OpenSSH only supports "gssapi-with-mic"
57 + * for now. We will still map any userauth method
58 + * prefixed with "gssapi-" to the gssapi PAM service.
59 + */
60 + snprintf(svcname, BUFSIZ, "%s-gssapi",
61 + options.pam_service_prefix);
62 + }
63 + return svcname;
65 +#endif /* PAM_ENHANCEMENT */
67 static int
68 sshpam_init(struct ssh *ssh, Authctxt *authctxt)
70 @@ -702,23 +762,76 @@
71 fatal("Username too long from %s port %d",
72 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
73 #endif
75 +#ifdef PAM_ENHANCEMENT
76 + const char *pam_service;
77 + const char **ptr_pam_service = &pam_service;
78 + char *svc = NULL;
80 + svc = derive_pam_service_name(authctxt);
81 + debug3("PAM service is %s", svc);
82 +#endif
84 if (sshpam_handle == NULL) {
85 if (ssh == NULL) {
86 fatal("%s: called initially with no "
87 "packet context", __func__);
89 } if (sshpam_handle != NULL) {
90 +#ifdef PAM_ENHANCEMENT
91 + /* get the pam service name */
92 + sshpam_err = pam_get_item(sshpam_handle,
93 + PAM_SERVICE, (sshpam_const void **)ptr_pam_service);
94 + if (sshpam_err != PAM_SUCCESS)
95 + fatal("Failed to get the PAM service name");
96 + debug3("Previous pam_service is %s", pam_service ?
97 + pam_service : "NULL");
99 + /* get the pam user name */
100 + sshpam_err = pam_get_item(sshpam_handle,
101 + PAM_USER, (sshpam_const void **)ptr_pam_user);
103 + /*
104 + * only need to re-start if either user or service is
105 + * different.
106 + */
107 + if (sshpam_err == PAM_SUCCESS && strcmp(user, pam_user) == 0
108 + && strncmp(svc, pam_service, strlen(svc)) == 0) {
109 + free(svc);
110 + return (0);
113 + /*
114 + * Clean up previous PAM state. No need to clean up session
115 + * and creds.
116 + */
117 + sshpam_authenticated = 0;
118 + sshpam_account_status = -1;
120 + sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, NULL);
121 + if (sshpam_err != PAM_SUCCESS)
122 + debug3("Cannot remove PAM conv"); /* a warning only */
123 +#else /* Original */
124 /* We already have a PAM context; check if the user matches */
125 sshpam_err = pam_get_item(sshpam_handle,
126 PAM_USER, (sshpam_const void **)ptr_pam_user);
127 if (sshpam_err == PAM_SUCCESS && strcmp(user, pam_user) == 0)
128 return (0);
129 +#endif /* PAM_ENHANCEMENT */
130 pam_end(sshpam_handle, sshpam_err);
131 sshpam_handle = NULL;
133 debug("PAM: initializing for \"%s\"", user);
134 +#ifdef PAM_ENHANCEMENT
135 + debug3("Starting PAM service %s for user %s method %s", svc, user,
136 + authctxt->authmethod_name);
137 + sshpam_err =
138 + pam_start(svc, user, &store_conv, &sshpam_handle);
139 + free(svc);
140 +#else /* Original */
141 sshpam_err =
142 pam_start(SSHD_PAM_SERVICE, user, &store_conv, &sshpam_handle);
143 +#endif
144 sshpam_authctxt = authctxt;
146 if (sshpam_err != PAM_SUCCESS) {
147 --- hpn-ssh-hpn-18.4.2/auth.h.orig
148 +++ hpn-ssh-hpn-18.4.2/auth.h
149 @@ -95,6 +95,9 @@
151 /* Information exposed to session */
152 struct sshbuf *session_info; /* Auth info for environment */
153 +#ifdef PAM_ENHANCEMENT
154 + char *authmethod_name;
155 +#endif
159 --- hpn-ssh-hpn-18.4.2/auth2.c.orig
160 +++ hpn-ssh-hpn-18.4.2/auth2.c
161 @@ -317,9 +317,17 @@
162 #endif
164 #ifdef USE_PAM
165 +#ifdef PAM_ENHANCEMENT
166 + /*
167 + * Start PAM here and once only, if each userauth does not
168 + * has its own PAM service.
169 + */
170 + if (options.use_pam && !options.pam_service_per_authmethod)
171 +#else
172 if (options.use_pam)
173 +#endif /* PAM_ENHANCEMENT */
174 PRIVSEP(start_pam(ssh));
175 -#endif
176 +#endif /* USE_PAM */
177 ssh_packet_set_log_preamble(ssh, "%suser %s",
178 authctxt->valid ? "authenticating " : "invalid ", user);
179 setproctitle("%s%s", authctxt->valid ? user : "unknown",
180 @@ -356,6 +364,18 @@
181 /* try to authenticate user */
182 m = authmethod_lookup(authctxt, method);
183 if (m != NULL && authctxt->failures < options.max_authtries) {
185 +#if defined(USE_PAM) && defined(PAM_ENHANCEMENT)
186 + /* start PAM service for each userauth */
187 + if (options.use_pam && options.pam_service_per_authmethod) {
188 + if (authctxt->authmethod_name != NULL)
189 + free(authctxt->authmethod_name);
190 + authctxt->authmethod_name = xstrdup(method);
191 + if (use_privsep)
192 + mm_inform_authmethod(method);
193 + PRIVSEP(start_pam(authctxt));
195 +#endif
196 debug2("input_userauth_request: try method %s", method);
197 authenticated = m->userauth(ssh, method);
199 @@ -381,6 +401,10 @@
200 char *methods;
201 int r, partial = 0;
203 +#ifdef PAM_ENHANCEMENT
204 + debug3("%s: entering", __func__);
205 +#endif
207 if (authenticated) {
208 if (!authctxt->valid) {
209 fatal("INTERNAL ERROR: authenticated invalid user %s",
210 @@ -404,6 +428,25 @@
213 if (authenticated && options.num_auth_methods != 0) {
215 +#if defined(USE_PAM) && defined(PAM_ENHANCEMENT)
216 + /*
217 + * If each userauth has its own PAM service, then PAM needs to
218 + * perform the account check for this service.
219 + */
220 + if (options.use_pam && options.pam_service_per_authmethod &&
221 + !PRIVSEP(do_pam_account())) {
222 + /* if PAM returned a message, send it to the user */
223 + if (sshbuf_len(loginmsg) > 0) {
224 + sshbuf_put(loginmsg, "\0", 1);
225 + userauth_send_banner(ssh, sshbuf_ptr(loginmsg));
226 + ssh_packet_write_wait(ssh);
229 + fatal("Access denied for user %s by PAM account "
230 + "configuration", authctxt->user);
232 +#endif
233 if (!auth2_update_methods_lists(authctxt, method, submethod)) {
234 authenticated = 0;
235 partial = 1;
236 @@ -421,7 +464,19 @@
237 return;
239 #ifdef USE_PAM
240 +#ifdef PAM_ENHANCEMENT
241 + /*
242 + * PAM needs to perform account checks after auth. However, if each
243 + * userauth has its own PAM service and options.num_auth_methods != 0,
244 + * then no need to perform account checking, because it was done
245 + * already.
246 + */
247 + if (options.use_pam && authenticated &&
248 + !(options.num_auth_methods != 0 &&
249 + options.pam_service_per_authmethod)) {
250 +#else
251 if (options.use_pam && authenticated) {
252 +#endif
253 int r, success = PRIVSEP(do_pam_account());
255 /* If PAM returned a message, send it to the user. */
256 --- hpn-ssh-hpn-18.4.2/monitor.c.orig
257 +++ hpn-ssh-hpn-18.4.2/monitor.c
258 @@ -117,6 +117,9 @@
259 int mm_answer_pwnamallow(struct ssh *, int, struct sshbuf *);
260 int mm_answer_auth2_read_banner(struct ssh *, int, struct sshbuf *);
261 int mm_answer_authserv(struct ssh *, int, struct sshbuf *);
262 +#ifdef PAM_ENHANCEMENT
263 +int mm_answer_authmethod(struct ssh *, int, struct sshbuf *);
264 +#endif
265 int mm_answer_authpassword(struct ssh *, int, struct sshbuf *);
266 int mm_answer_bsdauthquery(struct ssh *, int, struct sshbuf *);
267 int mm_answer_bsdauthrespond(struct ssh *, int, struct sshbuf *);
268 @@ -190,10 +193,17 @@
269 {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
270 {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
271 {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
272 +#ifdef PAM_ENHANCEMENT
273 + {MONITOR_REQ_AUTHMETHOD, MON_ISAUTH, mm_answer_authmethod},
274 +#endif
275 {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
276 {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
277 #ifdef USE_PAM
278 +#ifdef PAM_ENHANCEMENT
279 + {MONITOR_REQ_PAM_START, MON_ISAUTH, mm_answer_pam_start},
280 +#else
281 {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start},
282 +#endif
283 {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account},
284 {MONITOR_REQ_PAM_INIT_CTX, MON_ONCE, mm_answer_pam_init_ctx},
285 {MONITOR_REQ_PAM_QUERY, 0, mm_answer_pam_query},
286 @@ -300,6 +310,25 @@
288 /* Special handling for multiple required authentications */
289 if (options.num_auth_methods != 0) {
291 +#if defined(USE_PAM) && defined(PAM_ENHANCEMENT)
292 + /*
293 + * If each userauth has its own PAM service, then PAM
294 + * need to perform account check for this service.
295 + */
296 + if (options.use_pam && authenticated &&
297 + options.pam_service_per_authmethod) {
298 + struct sshbuf *m;
299 + if ((m = sshbuf_new()) == NULL)
300 + fatal("%s: sshbuf_new", __func__);
301 + mm_request_receive_expect(pmonitor->m_sendfd,
302 + MONITOR_REQ_PAM_ACCOUNT, m);
303 + authenticated = mm_answer_pam_account(ssh,
304 + pmonitor->m_sendfd, m);
305 + sshbuf_free(m);
307 +#endif
309 if (authenticated &&
310 !auth2_update_methods_lists(authctxt,
311 auth_method, auth_submethod)) {
312 @@ -317,8 +346,21 @@
313 !auth_root_allowed(ssh, auth_method))
314 authenticated = 0;
315 #ifdef USE_PAM
316 +#ifdef PAM_ENHANCEMENT
317 + /*
318 + * PAM needs to perform account checks after auth.
319 + * However, if each userauth has its own PAM service
320 + * and options.num_auth_methods != 0, then no need to
321 + * perform account checking, because it was done
322 + * already.
323 + */
324 + if (options.use_pam && authenticated &&
325 + !(options.num_auth_methods != 0 &&
326 + options.pam_service_per_authmethod)) {
327 +#else
328 /* PAM needs to perform account checks after auth */
329 if (options.use_pam && authenticated) {
330 +#endif
331 struct sshbuf *m;
333 if ((m = sshbuf_new()) == NULL)
334 @@ -802,6 +844,11 @@
335 monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
336 monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
338 +#ifdef PAM_ENHANCEMENT
339 + /* Allow authmethod information on the auth context */
340 + monitor_permit(mon_dispatch, MONITOR_REQ_AUTHMETHOD, 1);
341 +#endif
343 #ifdef USE_PAM
344 if (options.use_pam)
345 monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1);
346 @@ -825,6 +872,27 @@
347 return (0);
350 +#ifdef PAM_ENHANCEMENT
351 +int
352 +mm_answer_authmethod(struct ssh *ssh, int sock, struct sshbuf *m)
354 + Authctxt *authctxt = ssh->authctxt;
356 + monitor_permit_authentications(1);
357 + /*sshbuf_dump(m, stderr);*/
358 + sshbuf_get_cstring(m, &authctxt->authmethod_name, NULL);
359 + debug3("%s: authmethod_name=%s", __func__, authctxt->authmethod_name);
361 + if (authctxt->authmethod_name &&
362 + strlen(authctxt->authmethod_name) == 0) {
363 + free(authctxt->authmethod_name);
364 + authctxt->authmethod_name = NULL;
367 + return (0);
369 +#endif
372 mm_answer_authserv(struct ssh *ssh, int sock, struct sshbuf *m)
374 --- hpn-ssh-hpn-18.4.2/monitor.h.orig
375 +++ hpn-ssh-hpn-18.4.2/monitor.h
376 @@ -63,6 +63,9 @@
377 MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111,
378 MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113,
380 +#ifdef PAM_ENHANCEMENT
381 + MONITOR_REQ_AUTHMETHOD = 114,
382 +#endif
385 struct ssh;
386 --- hpn-ssh-hpn-18.4.2/monitor_wrap.c.orig
387 +++ hpn-ssh-hpn-18.4.2/monitor_wrap.c
388 @@ -396,6 +396,24 @@
389 sshbuf_free(m);
392 +#ifdef PAM_ENHANCEMENT
393 +/* Inform the privileged process about the authentication method */
394 +void
395 +mm_inform_authmethod(char *authmethod)
397 + struct sshbuf *m;
399 + debug3("%s entering", __func__);
400 + if ((m = sshbuf_new()) == NULL)
401 + fatal("%s: sshbuf_new", __func__);
402 + sshbuf_put_cstring(m, authmethod);
404 + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHMETHOD, m);
406 + sshbuf_free(m);
408 +#endif
410 /* Do the password authentication */
412 mm_auth_password(struct ssh *ssh, char *password)
413 --- hpn-ssh-hpn-18.4.2/servconf.c.orig
414 +++ hpn-ssh-hpn-18.4.2/servconf.c
415 @@ -202,6 +202,18 @@
416 options->channel_timeouts = NULL;
417 options->num_channel_timeouts = 0;
418 options->unused_connection_timeout = -1;
419 +#ifdef PAM_ENHANCEMENT
420 + options->pam_service_name = NULL;
421 + options->pam_service_prefix = NULL;
423 + /*
424 + * Each user method will have its own PAM service by default.
425 + * However, if PAMServiceName is specified
426 + * then there will be only one PAM service for the
427 + * entire user authentication.
428 + */
429 + options->pam_service_per_authmethod = 1;
430 +#endif
433 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
434 @@ -451,6 +463,12 @@
435 options->ip_qos_bulk = IPTOS_DSCP_CS1;
436 if (options->version_addendum == NULL)
437 options->version_addendum = xstrdup("");
439 +#ifdef PAM_ENHANCEMENT
440 + if (options->pam_service_prefix == NULL)
441 + options->pam_service_prefix = _SSH_PAM_SERVICE_PREFIX;
442 +#endif
444 if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
445 options->fwd_opts.streamlocal_bind_mask = 0177;
446 if (options->fwd_opts.streamlocal_bind_unlink == -1)
447 @@ -543,6 +561,9 @@
448 sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory,
449 sUsePrivilegeSeparation, sAllowAgentForwarding,
450 sHostCertificate, sInclude,
451 +#ifdef PAM_ENHANCEMENT
452 + sPAMServicePrefix, sPAMServiceName,
453 +#endif
454 sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
455 sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser,
456 sKexAlgorithms, sCASignatureAlgorithms, sIPQoS, sVersionAddendum,
457 @@ -694,6 +715,10 @@
458 { "forcecommand", sForceCommand, SSHCFG_ALL },
459 { "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
460 { "hostcertificate", sHostCertificate, SSHCFG_GLOBAL },
461 +#ifdef PAM_ENHANCEMENT
462 + { "pamserviceprefix", sPAMServicePrefix, SSHCFG_GLOBAL },
463 + { "pamservicename", sPAMServiceName, SSHCFG_GLOBAL },
464 +#endif
465 { "revokedkeys", sRevokedKeys, SSHCFG_ALL },
466 { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
467 { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
468 @@ -2649,6 +2674,37 @@
470 goto parse_time;
472 + case sPAMServicePrefix:
473 + arg = strdelim(&str);
474 + if (!arg || *arg == '\0')
475 + fatal("%s line %d: Missing argument.",
476 + filename, linenum);
477 + if (options->pam_service_name != NULL)
478 + fatal("%s line %d: PAMServiceName and PAMServicePrefix"
479 + " are mutually exclusive.", filename, linenum);
480 + if (options->pam_service_prefix == NULL)
481 + options->pam_service_prefix = xstrdup(arg);
482 + break;
484 + case sPAMServiceName:
485 + arg = strdelim(&str);
486 + if (!arg || *arg == '\0')
487 + fatal("%s line %d: Missing argument.",
488 + filename, linenum);
489 + if (options->pam_service_prefix != NULL)
490 + fatal("%s line %d: PAMServiceName and PAMServicePrefix"
491 + " are mutually exclusive.", filename, linenum);
492 + if (options->pam_service_name == NULL) {
493 + options->pam_service_name = xstrdup(arg);
495 + /*
496 + * When this option is specified, we will not have
497 + * PAM service for each auth method.
498 + */
499 + options->pam_service_per_authmethod = 0;
501 + break;
503 case sDeprecated:
504 case sIgnore:
505 case sUnsupported:
506 --- hpn-ssh-hpn-18.4.2/servconf.h.orig
507 +++ hpn-ssh-hpn-18.4.2/servconf.h
508 @@ -71,6 +71,10 @@
509 struct addrinfo *addrs;
512 +#ifdef PAM_ENHANCEMENT
513 +#define _SSH_PAM_SERVICE_PREFIX "sshd"
514 +#endif
516 typedef struct {
517 u_int num_ports;
518 u_int ports_from_cmdline;
519 @@ -227,6 +231,12 @@
520 u_int num_auth_methods;
521 char **auth_methods;
523 +#ifdef PAM_ENHANCEMENT
524 + char *pam_service_prefix;
525 + char *pam_service_name;
526 + int pam_service_per_authmethod;
527 +#endif
529 int fingerprint_hash;
530 int expose_userauth_info;
531 u_int64_t timing_secret;
532 --- hpn-ssh-hpn-18.4.2/hpnsshd.8.orig
533 +++ hpn-ssh-hpn-18.4.2/hpnsshd.8
534 @@ -1017,6 +1017,33 @@
535 started last).
536 The content of this file is not sensitive; it can be world-readable.
539 +.Sh SECURITY
540 +sshd uses pam(3PAM) for password and keyboard-interactive methods as well as
541 +for account management, session management, and the password management for all
542 +authentication methods.
543 +.Pp
544 +Each SSHv2 userauth type has its own PAM service name:
546 +.Bd -literal -offset 3n
548 +-----------------------------------------------
549 +| SSHv2 Userauth | PAM Service Name |
550 +-----------------------------------------------
551 +| none | sshd-none |
552 +-----------------------------------------------
553 +| password | sshd-password |
554 +-----------------------------------------------
555 +| keyboard-interactive | sshd-kbdint |
556 +-----------------------------------------------
557 +| pubkey | sshd-pubkey |
558 +-----------------------------------------------
559 +| hostbased | sshd-hostbased |
560 +-----------------------------------------------
561 +| gssapi-with-mic | sshd-gssapi |
562 +-----------------------------------------------
563 +.Ed
565 .Sh SEE ALSO
566 .Xr hpnscp 1 ,
567 .Xr hpnsftp 1 ,
568 --- hpn-ssh-hpn-18.4.2/hpnsshd_config.5.orig
569 +++ hpn-ssh-hpn-18.4.2/hpnsshd_config.5
570 @@ -1400,6 +1400,35 @@
571 protection against man-in-the-middle attacks. As with NoneEnabled all authentication
572 remains encrypted and integrity is ensured. Default is
573 .Cm no.
574 +.It Cm PAMServiceName
575 +Specifies the PAM service name for the PAM session.
576 +The
577 +.Cm PAMServiceName
578 +and
579 +.Cm PAMServicePrefix
580 +options are mutually exclusive and if both are set, sshd does not start.
581 +If this option is set the service name is the same for all user authentication
582 +methods.
583 +The option has no default value.
584 +See
585 +.Cm PAMServicePrefix
586 +for more information.
587 +.It Cm PAMServicePrefix
588 +Specifies the PAM service name prefix for service names used for individual
589 +user authentication methods.
590 +The default is sshd.
591 +The
592 +.Cm PAMServiceName
593 +and
594 +.Cm PAMServicePrefix
595 +options are mutually exclusive and if both are set, sshd does not start.
596 +.Pp
597 +For example, if this option is set to
598 +.Cm admincli ,
599 +the service name for the keyboard-interactive authentication method is
600 +.Sy admincli-kbdint
601 +instead of the default
602 +.Sy sshd-kbdint .
603 .It Cm PasswordAuthentication
604 Specifies whether password authentication is allowed.
605 The default is
606 @@ -1950,8 +1979,7 @@
607 is enabled, you will not be able to run
608 .Xr sshd 8
609 as a non-root user.
610 -The default is
611 -.Cm no .
612 +On OpenIndiana, the option is always enabled.
613 .It Cm VersionAddendum
614 Optionally specifies additional text to append to the SSH protocol banner
615 sent by the server upon connection.