1/* 2 * Copyright 2015 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel D��rfler, <axeld@pinc-software.de> 7 * Ingo Weinhold <ingo_weinhold@gmx.de> 8 */ 9 10 11#include <pwd.h> 12 13#include <Button.h> 14#include <Catalog.h> 15#include <LayoutBuilder.h> 16#include <NetworkSettings.h> 17#include <NetworkSettingsAddOn.h> 18#include <StringView.h> 19#include <TextView.h> 20 21#include <NetServer.h> 22#include <RegistrarDefs.h> 23#include <user_group.h> 24#include <util/KMessage.h> 25 26#include "ServiceListItem.h" 27#include "ServiceView.h" 28 29 30using namespace BNetworkKit; 31 32 33#undef B_TRANSLATION_CONTEXT 34#define B_TRANSLATION_CONTEXT "SSHServiceAddOn" 35 36 37static const uint32 kMsgToggleService = 'tgls'; 38 39 40class SSHServiceAddOn : public BNetworkSettingsAddOn { 41public: 42 SSHServiceAddOn(image_id image, 43 BNetworkSettings& settings); 44 virtual ~SSHServiceAddOn(); 45 46 virtual BNetworkSettingsItem* 47 CreateNextItem(uint32& cookie); 48}; 49 50 51class SSHServiceView : public ServiceView { 52public: 53 SSHServiceView(BNetworkSettings& settings); 54 virtual ~SSHServiceView(); 55 56protected: 57 virtual void Enable(); 58}; 59 60 61class SSHServiceItem : public BNetworkSettingsItem { 62public: 63 SSHServiceItem(BNetworkSettings& settings); 64 virtual ~SSHServiceItem(); 65 66 virtual BNetworkSettingsType 67 Type() const; 68 69 virtual BListItem* ListItem(); 70 virtual BView* View(); 71 72 virtual status_t Revert(); 73 virtual bool IsRevertable(); 74 75 virtual void SettingsUpdated(uint32 which); 76 77private: 78 BNetworkSettings& fSettings; 79 BListItem* fItem; 80 ServiceView* fView; 81}; 82 83 84// #pragma mark - 85 86 87SSHServiceView::SSHServiceView(BNetworkSettings& settings) 88 : 89 ServiceView("ssh", NULL, B_TRANSLATE("SSH server"), B_TRANSLATE( 90 "The SSH server allows you to " 91 "remotely access your machine with a terminal session, as well as " 92 "file access using the SCP and SFTP protocols."), settings) 93{ 94} 95 96 97SSHServiceView::~SSHServiceView() 98{ 99} 100 101 102void 103SSHServiceView::Enable() 104{ 105 if (getpwnam("sshd") == NULL) { 106 // We need to create a dedicated user for the service 107 // The following code is copied from useradd, and should be moved 108 // to a public class. 109 gid_t groupID = 100; 110 111 // Find an unused user ID 112 uid_t userID = 1000; 113 while (getpwuid(userID) != NULL) 114 userID++; 115 116 const char* home = "/boot/home"; 117 int expiration = 99999; 118 int inactive = -1; 119 const char* shell = "/bin/sh"; 120 const char* realName = ""; 121 122 int min = -1; 123 int max = -1; 124 int warn = 7; 125 126 // prepare request for the registrar 127 KMessage message(BPrivate::B_REG_UPDATE_USER); 128 if (message.AddInt32("uid", userID) == B_OK 129 && message.AddInt32("gid", groupID) == B_OK 130 && message.AddString("name", "sshd") == B_OK 131 && message.AddString("password", "x") == B_OK 132 && message.AddString("home", home) == B_OK 133 && message.AddString("shell", shell) == B_OK 134 && message.AddString("real name", realName) == B_OK 135 && message.AddString("shadow password", "!") == B_OK 136 && message.AddInt32("last changed", time(NULL)) == B_OK 137 && message.AddInt32("min", min) == B_OK 138 && message.AddInt32("max", max) == B_OK 139 && message.AddInt32("warn", warn) == B_OK 140 && message.AddInt32("inactive", inactive) == B_OK 141 && message.AddInt32("expiration", expiration) == B_OK 142 && message.AddInt32("flags", 0) == B_OK 143 && message.AddBool("add user", true) == B_OK) { 144 // send the request 145 KMessage reply; 146 status_t error = send_authentication_request_to_registrar(message, 147 reply); 148 if (error != B_OK) { 149 fprintf(stderr, "Error: Failed to create user: %s\n", 150 strerror(error)); 151 } 152 } 153 } 154 155 BNetworkServiceSettings settings; 156 settings.SetName("ssh"); 157 settings.SetStandAlone(true); 158 159 settings.AddArgument("/bin/sshd"); 160 settings.AddArgument("-D"); 161 162 BMessage service; 163 if (settings.GetMessage(service) == B_OK) 164 fSettings.AddService(service); 165} 166 167 168// #pragma mark - 169 170 171SSHServiceItem::SSHServiceItem(BNetworkSettings& settings) 172 : 173 fSettings(settings), 174 fItem(new ServiceListItem("ssh", B_TRANSLATE("SSH server"), settings)), 175 fView(NULL) 176{ 177} 178 179 180SSHServiceItem::~SSHServiceItem() 181{ 182 if (fView->Parent() == NULL) 183 delete fView; 184 185 delete fItem; 186} 187 188 189BNetworkSettingsType 190SSHServiceItem::Type() const 191{ 192 return B_NETWORK_SETTINGS_TYPE_SERVICE; 193} 194 195 196BListItem* 197SSHServiceItem::ListItem() 198{ 199 return fItem; 200} 201 202 203BView* 204SSHServiceItem::View() 205{ 206 if (fView == NULL) 207 fView = new SSHServiceView(fSettings); 208 209 return fView; 210} 211 212 213status_t 214SSHServiceItem::Revert() 215{ 216 return fView != NULL ? fView->Revert() : B_OK; 217} 218 219 220bool 221SSHServiceItem::IsRevertable() 222{ 223 return fView != NULL ? fView->IsRevertable() : false; 224} 225 226 227void 228SSHServiceItem::SettingsUpdated(uint32 which) 229{ 230 if (fView != NULL) 231 fView->SettingsUpdated(which); 232} 233 234 235// #pragma mark - 236 237 238SSHServiceAddOn::SSHServiceAddOn(image_id image, 239 BNetworkSettings& settings) 240 : 241 BNetworkSettingsAddOn(image, settings) 242{ 243} 244 245 246SSHServiceAddOn::~SSHServiceAddOn() 247{ 248} 249 250 251BNetworkSettingsItem* 252SSHServiceAddOn::CreateNextItem(uint32& cookie) 253{ 254 if (cookie++ == 0) 255 return new SSHServiceItem(Settings()); 256 257 return NULL; 258} 259 260 261// #pragma mark - 262 263 264extern "C" 265BNetworkSettingsAddOn* 266instantiate_network_settings_add_on(image_id image, BNetworkSettings& settings) 267{ 268 return new SSHServiceAddOn(image, settings); 269} 270